我怀疑之前有人问过这个问题,但似乎找不到匹配的问题……
我使用的是Scala,但我很确定这只是一个Java问题……输入值为双精度
println(28.0 / 5.6)
println(28.0 % 5.6)这些行的结果是
5.0
1.7763568394002505E-15 这意味着Java正确地执行了除法,但由于某种原因,模数错误,因为对于任何可以解决整数的除法问题,模数应该是0……
有解决这个问题的办法吗?
谢谢!
发布于 2011-08-17 03:11:01
5.0只是显示了Java理解的精确结果比任何其他双精度值更接近5.0。这并不意味着运算的精确结果恰好是5。
现在,当你询问模数时,你可以得到一个更精细的细节级别,因为结果并不是固定在"5“部分。
这不是一个很好的解释,但是假设你有一个精度为4位的十进制浮点类型。1000 / 99.99和1000%99.99的结果是什么?
好的,实际结果从10.001001开始-所以你必须将其舍入到10.00.但是,余数是0.10,这是可以表示的。再说一次,看起来除法给了你一个整数,但它不完全是。
考虑到这一点,请记住您的文字5.6实际上是5.5999999999999996447286321199499070644378662109375.现在很明显,28.0 (*可以)精确地除以这个数字并不是5。
编辑:现在,如果您使用BigDecimal执行十进制浮点运算的结果,该值实际上是5.6,并且没有问题:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("28.0");
BigDecimal y = new BigDecimal("5.6");
BigDecimal div = x.divide(y);
BigDecimal rem = x.remainder(y);
System.out.println(div); // Prints 5
System.out.println(rem); // Prints 0.0
}
}发布于 2011-08-17 03:13:23
结果实际上不是0.00000000000000177635,但非常接近( 0.00000000000000177635...)。问题是一些十进制数不能精确地用二进制表示,所以这就是问题所在;我怀疑用C/C++也会打印出同样的结果。
发布于 2012-11-28 02:54:47
这是我使用模运算符检查双精度值是否可被另一个整除的解决方案:
public class DoubleOperation
{
public static final double EPSILON = 0.000001d;
public static boolean equals(double val1, double val2)
{
return (Math.abs(val1 - val2) < EPSILON);
}
public static boolean divisible(double dividend, double divisor)
{
double divisionRemainder = dividend % divisor;
return (equals(divisionRemainder, 0.0d) || equals(divisionRemainder, divisor));
}
}https://stackoverflow.com/questions/7083625
复制相似问题