Java8 中的 RoundingMode.HALF_DOWN 问题
我使用的是 jdk 1.8.0_45,我们的测试发现了 roding 的一个 bug.RoundingMode.HALF_DOWN 与 RoundingMode.HALF_UP 相同,决定舍入的最后一位小数为 5.
I am using jdk 1.8.0_45, and our tests discovered a bug in rouding. RoundingMode.HALF_DOWN works the same as RoundingMode.HALF_UP when the last decimal that decide the rounding is 5.
我发现了与 RoundingMode.HALF_UP 相关的问题,但它们已在更新 40 中修复.我还向 oracle 提出了一个错误,但根据我的经验,它们确实没有响应.
I found related issues with RoundingMode.HALF_UP, but they are fixed in update 40. I also put a bug to the oracle, but from my experience they are really unresponsive.
package testjava8;
import java.math.RoundingMode;
import java.text.DecimalFormat;
public class Formatori {
public static void main(String[] args) {
DecimalFormat format = new DecimalFormat("#,##0.0000");
format.setRoundingMode(RoundingMode.HALF_DOWN);
Double toFormat = 10.55555;
System.out.println("Round down");
System.out.println(format.format(toFormat));
format.setRoundingMode(RoundingMode.HALF_UP);
toFormat = 10.55555;
System.out.println("Round up");
System.out.println(format.format(toFormat));
}
}
实际结果:向下舍入10.5556围捕10.5556
Actual result: Round down 10.5556 Round up 10.5556
预期结果(使用 jdk 1.7 获得):向下舍入10.5555围捕10.5556
Expected result(obtain with jdk 1.7): Round down 10.5555 Round up 10.5556
推荐答案
看来是打算改了.JDK 1.7 的行为不正确.
Seems that it's intended change. The JDK 1.7 behavior was incorrect.
问题在于您只是不能使用 double
类型表示数字 10.55555
.它以 IEEE 二进制格式存储数据,因此当您将十进制 10.55555
数字分配给 double
变量时,您实际上得到了可以用 IEEE 格式表示的最接近的值:10.555550000000000210320649784989655017852783203125
.此数字大于 10.55555
,因此在 HALF_DOWN
模式下正确四舍五入为 10.5556
.
The problem is that you simply cannot represent the number 10.55555
using the double
type. It stores the data in IEEE binary format, so when you assign the decimal 10.55555
number to the double
variable, you actually get the closest value which can be represented in IEEE format: 10.555550000000000210320649784989655017852783203125
. This number is bigger than 10.55555
, so it's correctly rounded to 10.5556
in HALF_DOWN
mode.
您可以检查一些可以精确表示为二进制的数字.例如,10.15625
(即 10 + 5/32
,因此是二进制的 1010.00101
).此数字在 HALF_DOWN
模式下四舍五入为 10.1562
,在 HALF_UP
模式下四舍五入为 10.1563
.
You can check some numbers which can be exactly represented in binary. For example, 10.15625
(which is 10 + 5/32
, thus 1010.00101
in binary). This number is rounded to 10.1562
in HALF_DOWN
mode and 10.1563
in HALF_UP
mode.
如果您想恢复旧的行为,您可以先使用 BigDecimal/java/math/BigDecimal.html#valueOf-double-">BigDecimal.valueOf
构造函数,将 double
转换为 BigDecimal
,使用 double
的规范字符串表示":
If you want to restore the old behavior, you can first convert your number to BigDecimal
using BigDecimal.valueOf
constructor, which "translates a double
into a BigDecimal
, using the double
's canonical string representation":
BigDecimal toFormat = BigDecimal.valueOf(10.55555);
System.out.println("Round down");
System.out.println(format.format(toFormat)); // 10.5555
format.setRoundingMode(RoundingMode.HALF_UP);
toFormat = BigDecimal.valueOf(10.55555);
System.out.println("Round up");
System.out.println(format.format(toFormat)); // 10.5556
相关文章