Modulus with doubles in Java

最后都变了- 提交于 2019-11-27 14:06:13

Use a precise type if you need a precise result:

    double val = 3.9 - (3.9 % 0.1);
    System.out.println(val); // 3.8000000000000003

    BigDecimal x = new BigDecimal( "3.9" );
    BigDecimal bdVal = x.subtract( x.remainder( new BigDecimal( "0.1" ) ) );
    System.out.println(bdVal); // 3.9

Why 3.8000...003? Because Java uses the FPU to calculate the result. 3.9 is impossible to store exactly in IEEE double precision notation, so it stores 3.89999... instead. And 3.8999%0.01 gives 0.09999... hence the result is a little bit bigger than 3.8.

From The Java Language Specification:

The result of a floating-point remainder operation as computed by the % operator is not the same as that produced by the remainder operation defined by IEEE 754. The IEEE 754 remainder operation computes the remainder from a rounding division, not a truncating division, and so its behavior is not analogous to that of the usual integer remainder operator. Instead, the Java programming language defines % on floating-point operations to behave in a manner analogous to that of the integer remainder operator; this may be compared with the C library function fmod. The IEEE 754 remainder operation may be computed by the library routine Math.IEEEremainder.

In other words, this is due to the fact that Java rounds the result of the division involved in computing the remainder, while IEEE754 specifies truncating the answer of the division. This particular case seems to expose this difference very clearly.

You can get the answer you expect using Math.IEEEremainder:

System.out.println(3.9 - (3.9 % 0.1));
System.out.println(3.9 - Math.IEEEremainder(3.9, 0.1));

You could use java.math.BigDecimal and its method divideAndRemainder().

If you know the amount of decimals you're dealing with, you could try to convert to integers first. This is just a classic case of floating point inacuraccy. Instead of doing 3.9 % 0.1 you're doing something like 3.899 % 0.0999

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!