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

2022-08-31 20:52:42

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

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


答案 1

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

答案 2

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

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