Java8中的RoundingMode.HALF_DOWN问题 [英] RoundingMode.HALF_DOWN issue in Java8
问题描述
我使用的是jdk 1.8.0_45,我们的测试发现了一个错误。
当决定舍入的最后一个小数是5时,RoundingMode.HALF_DOWN与RoundingMode.HALF_UP的工作方式相同。
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中添加了一个bug,但根据我的经验,它们确实没有响应。
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.
问题是你只是不能代表数字 10.55555
使用 double
类型。它以IEEE二进制格式存储数据,因此当您将小数 10.55555
数字分配给 double
变量时,实际上获得可以用IEEE格式表示的最接近的值: 10.555550000000000210320649784989655017852783203125
。此数字大于 10.55555
,因此在 HALF_DOWN $中正确舍入为
10.5556
c $ c> mode。
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
, 10.1563
在 HALF_UP
模式。
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
使用 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
这篇关于Java8中的RoundingMode.HALF_DOWN问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!