Modulo不起作用

时间:2011-09-27 00:33:42

标签: java modulo

我知道这似乎是一个非常愚蠢的问题,但我不明白为什么这不起作用。这样:

 System.out.println(5 % .10);

它正在回归:

0.09999999999999973

我真的没有想法。我只是在学习Java,而且我对C#非常好,所以我尝试用C#来。 C#似乎也回归了同样的事情。

5 个答案:

答案 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.

注意:结果仍然会有轻微的错误,但是它会足够小​​,当你打印它时,你将看不到它。