我知道这似乎是一个非常愚蠢的问题,但我不明白为什么这不起作用。这样:
System.out.println(5 % .10);
它正在回归:
0.09999999999999973
我真的没有想法。我只是在学习Java,而且我对C#非常好,所以我尝试用C#来。 C#似乎也回归了同样的事情。
答案 0 :(得分:8)
这是由于浮点精度。 0.10
无法用二进制表示。因此,结果并非完全0.10
,因此未归结为0
。
这适用于0.25
,因为0.25
可以完全用二进制表示。
编辑:
通常,任何可以表示为分母中具有2的幂的分数的数字都可以在IEEE浮点中精确表示。 (只要它没有上溢/下溢)
答案 1 :(得分:8)
正如其他人所解释的那样,这是由于浮点精度造成的不准确。
您应该使用BigDecimal,在这种情况下使用remainder method进行精确算术,包括小数。
BigDecimal number = new BigDecimal(5);
BigDecimal divisor = new BigDecimal("0.1");
BigDecimal result = number.remainder(divisor);
System.out.println(result); // 0
答案 2 :(得分:2)
你正在做浮点运算。 0.1没有精确的浮动表示。
答案 3 :(得分:1)
Java(与COBOL以外的大多数编程语言一样)正在二进制系统中进行计算。我认为0.10有这样一个不幸的二进制表示,你的计算结果看起来像这样。我认为最好避免计算double或float的模数,并坚持使用整数或长整数来获得更好的结果。
答案 4 :(得分: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 d = 5;
double mod0_1 = d * 10 % 1 / 10;
double rounded = Math.round(mod0_1 * 1e12)/1e12; // round to 12 places.
注意:结果仍然会有轻微的错误,但是它会足够小,当你打印它时,你将看不到它。