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

Cri*_*ian 45 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
Run Code Online (Sandbox Code Playgroud)

为什么会这样?为什么我得到这些值而不是0.65

Pet*_*rey 42

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);
Run Code Online (Sandbox Code Playgroud)

打印

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
Run Code Online (Sandbox Code Playgroud)


Vin*_*ing 23

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

float n = 22.65f;
float x = n - (int) n;
Run Code Online (Sandbox Code Playgroud)

  • 这将给出舍入错误 try: float a = 22.3f; a - (int)(a) 结果将是 0.29999924 而不是 0.3 (2认同)

Nik*_*bak 7

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

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

 System.out.printf("%.20f\n", 0.65f);
Run Code Online (Sandbox Code Playgroud)

- >

 0.64999997615814210000
Run Code Online (Sandbox Code Playgroud)

编辑
舍入误差,其计算过程中蓄积,也是它发挥作用,为他人注意.


rod*_*ion 7

我有点长但工作:

BigDecimal.valueOf(2.65d).divideAndRemainder(BigDecimal.ONE)[1].floatValue()
Run Code Online (Sandbox Code Playgroud)


Gho*_*ani 6

获取 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);
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试这个。如果计时器为10.65,则h最终为前两位小数 * 100 = 65。

这是一种快速简单的方法来分离您想要的内容,而不会出现舍入问题。

float h = (int)((timer % 1) * 100);
Run Code Online (Sandbox Code Playgroud)