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

时间:2011-02-16 13:34:02

标签: 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

10 个答案:

答案 0 :(得分:41)

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

答案 1 :(得分:18)

我认为这是最简单的方法:

float n = 22.65f;
float x = n - (int) n;

答案 2 :(得分:7)

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

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

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

- >

 0.64999997615814210000

修改
正如其他人所指出的那样,在计算过程中累积的舍入误差也会在其中起作用。

答案 3 :(得分:7)

我有点长但是有效:

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

答案 4 :(得分:3)

如果您只想将数字打印到2dp,可以使用DecimalFormat。

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

如果你想在内部使用BigDecimal

定点数

答案 5 :(得分:2)

简短回答:你不能用二进制表示一些精确的十进制数字。

答案很长:http://www-users.math.umd.edu/~jkolesar/mait613/floating_point_math.pdf

<强> [编辑]

还有一个有趣的读物:http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

答案 6 :(得分:2)

试试这个。 如果计时器 10.65 ,则 h 结束,作为前两位小数* 100 = 65。

这是一种快速简便的方法,可以在没有舍入问题的情况下分离您想要的内容。

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

答案 7 :(得分:2)

获取float和double数据类型的小数部分的声音和完美方法是使用String这样的代码:

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

答案 8 :(得分:0)

答案 9 :(得分:0)

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

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);