我知道这可能是一个非常愚蠢的问题,但我就是不明白为什么它不能正常工作。这是:
System.out.println(5 % .10);
并且它返回:
0.09999999999999973
我真的不知道。我正在学习Java,并且我对C#也很熟练,所以我也尝试使用C#来解决问题。但C#似乎返回了相同的结果。
我知道这可能是一个非常愚蠢的问题,但我就是不明白为什么它不能正常工作。这是:
System.out.println(5 % .10);
并且它返回:
0.09999999999999973
我真的不知道。我正在学习Java,并且我对C#也很熟练,所以我也尝试使用C#来解决问题。但C#似乎返回了相同的结果。
0.10
在二进制中无法被准确表示。因此,结果并不完全是0.10
,因此不能被模除为0
。0.25
有效,因为0.25
可以在二进制中准确表示。正如其他人所解释的那样,这是由于浮点精度不准确导致的。
在涉及小数的精确算术中,您应该使用BigDecimal,在这种情况下使用余数方法。
BigDecimal number = new BigDecimal(5);
BigDecimal divisor = new BigDecimal("0.1");
BigDecimal result = number.remainder(divisor);
System.out.println(result); // 0
您正在进行浮点运算。0.1在浮点数中没有精确的表示。
0.1 的二进制表示为
System.out.println(new BigDecimal(0.1));
打印
0.1000000000000000055511151231257827021181583404541015625
当你打印0.1时,会有一点四舍五入的情况出现,这掩盖了这个错误。
在进行计算时,必须使用BigDecimal或将结果四舍五入或转换计算以最小化误差。
5 % 0.1
(5 / 0.1 % 1) * 0.1
50 % 1 / 10
关于 double 类型,你可以这样做
double d = 5;
double mod0_1 = d * 10 % 1 / 10;
double rounded = Math.round(mod0_1 * 1e12)/1e12; // round to 12 places.
Java(像大多数编程语言一样,除了COBOL)在二进制系统中进行计算。我认为0.10具有如此不幸的二进制表示形式,以至于您的计算结果看起来像这样。我认为最好避免计算双精度或浮点数的模数,并坚持使用整数或长整型以获得更好的结果。