Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何获取浮点的小数部分?_Java_Floating Point - Fatal编程技术网

Java 如何获取浮点的小数部分?

Java 如何获取浮点的小数部分?,java,floating-point,Java,Floating Point,我需要提取浮点数的小数部分,但我得到了奇怪的结果: float n = 22.65f; // I want x = 0.65f, but... x = n % 1; // x = 0.6499996 x = n - Math.floor(n); // x = 0.6499996185302734 x = n - (int)n; // x = 0.6499996 为什么会发生这种情况?为什么我要得到这些值而不是0.65?因为并非所有有理数都可以表示为浮点数,0.6499996…是0.65的

我需要提取浮点数的小数部分,但我得到了奇怪的结果:

float n = 22.65f;
// I want x = 0.65f, but...

x = n % 1; // x = 0.6499996

x = n - Math.floor(n); // x = 0.6499996185302734

x = n - (int)n; // x = 0.6499996

为什么会发生这种情况?为什么我要得到这些值而不是
0.65

因为并非所有有理数都可以表示为浮点数,
0.6499996…
0.65
的最接近值

例如,尝试打印数字的前20位
0.65

 System.out.printf("%.20f\n", 0.65f);
->

编辑

正如其他人所指出的,在计算过程中累积的舍入误差也在其中发挥作用。

float
只有几位数的精度,因此您应该很容易看到舍入误差。请尝试使用
double
此选项精度更高,但仍存在舍入错误。你必须对得到的任何答案进行四舍五入,才能得到一个合理的结果

如果这不是你想要的,你可以使用BigDecimal,它没有舍入误差,但是有它自己的头疼问题

编辑:你可能会发现这很有趣。默认的Float.toString()使用最小舍入,但通常这还不够

System.out.println("With no rounding");
float n = 22.65f;
System.out.println("n= "+new BigDecimal(n));
float expected = 0.65f;
System.out.println("expected= "+new BigDecimal(expected));

System.out.println("n % 1= "+new BigDecimal(n % 1));
System.out.println("n - Math.floor(n) = "+new BigDecimal(n - Math.floor(n)));
System.out.println("n - (int)n= "+new BigDecimal(n - (int)n));

System.out.println("With rounding");
System.out.printf("n %% 1= %.2f%n", n % 1);
System.out.printf("n - Math.floor(n) = %.2f%n", n - Math.floor(n));
System.out.printf("n - (int)n= %.2f%n", n - (int)n);
印刷品

With no rounding
n= 22.6499996185302734375
expected= 0.64999997615814208984375
n % 1= 0.6499996185302734375
n - Math.floor(n) = 0.6499996185302734375
n - (int)n= 0.6499996185302734375
With rounding
n % 1= 0.65
n - Math.floor(n) = 0.65
n - (int)n= 0.65
试试看

我有点长,但有效:

BigDecimal.valueOf(2.65d).divideAndRemainder(BigDecimal.ONE)[1].floatValue()

简短回答:有些数字在二进制中不能精确表示,而在十进制中则是“精确”的

长答覆:

[编辑]


还有一个有趣的阅读:

如果您只想将数字打印为2dp,可以使用十进制格式

DecimalFormat df= new DecimalFormat("#.##");
System.out.println(df.format(f));

如果您想在内部使用定点数字,请使用BigDecimal,我认为这是最简单的方法:

float n = 22.65f;
float x = n - (int) n;
试试这个。 如果计时器为10.65,则h以小数点后两位结束*100=65

这是一种快速简便的方法,可以在不存在舍入问题的情况下分离所需内容

float h = (int)((timer % 1) * 100);

获取浮点和双精度数据类型小数部分的完美方法是使用字符串,如下代码所示:

float num=2.35f;
String s= new Float(num).toString();
String p=s.substring(s.indexOf('.')+1,s.length());
int decimal=Integer.parseInt(p);

此代码适用于任意数量的十进制数字

float f = 2.3445f;
String s = Float.toString(f);
char[] c = s.toCharArray();
int length = s.length();
int flag = 0;
StringBuilder n = new StringBuilder();
for(int i = 0; i < length; i++)
{
    if(flag == 1)
    {
        n.append(c[i]);
    }
    if(c[i] == '.')
    {
        flag = 1;
    }
}
String result = n.toString();
int answer = Integer.parseInt(result);
System.out.println(answer);
float f=2.3445f;
字符串s=Float.toString(f);
char[]c=s.toCharArray();
int length=s.length();
int标志=0;
StringBuilder n=新的StringBuilder();
for(int i=0;i
添加了另一个有趣的选项:)+1个很棒的东西@Peter,谢谢。如果保证
n-Math.floor(n)
<1.0,你知道吗?有没有可能,因为浮点的奇怪,1.999999999。。。如果1.999999999999999实际表示为2,则只能得到>=1?@Gray。如果从浮点中减去浮点的整数部分,则不应使其向上取整。它可能会暴露潜在的表示错误。通过删除整数部分,可以使结果的精度高于表示值所需的精度。你能举出一个让人感到奇怪的值的例子吗?不,我不能@Peter。我只是在写一些防御代码。我很少使用浮点数(幸运的是),我只是想知道。你的解释有道理。谢谢。这将产生舍入误差。请尝试:浮点a=22.3f;a-(int)(a)结果将为0.2999924,而不是0。3@SvenRojek不要对非代码的文本使用代码格式。对于
50.01
,由于使用浮点数据类型,它有时会给出
0
。对于那些对问题的描述似乎能回答这一事实感到困惑的人,整个线程是人们向用户解释的,仅仅因为你把22.65作为一个文本,并不意味着数字可以以二进制形式存储。浮动没有无限的精度,如果你只是打印
n
,你仍然会得到
6.4999…
。有人能帮我吗,这对我来说不是很明显)。integerPart-BigDecimal.valueOf(weightInLB).divideandremainer(BigDecimal.ONE)[0].toInt()
float f = 2.3445f;
String s = Float.toString(f);
char[] c = s.toCharArray();
int length = s.length();
int flag = 0;
StringBuilder n = new StringBuilder();
for(int i = 0; i < length; i++)
{
    if(flag == 1)
    {
        n.append(c[i]);
    }
    if(c[i] == '.')
    {
        flag = 1;
    }
}
String result = n.toString();
int answer = Integer.parseInt(result);
System.out.println(answer);