Java模运算符导致错误的结果?

Sam*_*ley 4 java floating-point floating-accuracy modulo

我怀疑之前有人问过,但似乎找不到符合的问题......

我正在使用Scala,但我很确定这只是一个Java问题......输入值是双倍的

println(28.0 / 5.6) 
println(28.0 % 5.6)
Run Code Online (Sandbox Code Playgroud)

这些线的结果是

5.0 
1.7763568394002505E-15 
Run Code Online (Sandbox Code Playgroud)

这意味着Java正确执行除法,但由于某种原因得到模数错误,因为对于任何解析为整数的除法问题,模数应为0 ...

这有解决方法吗?

谢谢!

Jon*_*eet 13

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
    }
}
Run Code Online (Sandbox Code Playgroud)