【发布时间】:2019-10-15 12:48:12
【问题描述】:
我在 open jdk1.8 中使用 NumberFormat.format(double) 时遇到了一些奇怪的问题。 我知道在此版本中修复了之前版本中的舍入问题,但仍然似乎有些不对劲。
public static void main (String args[]) {
double num = 16.34625;
NumberFormat nf = NumberFormat.getInstance();
nf.setGroupingUsed(false);
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(4);
System.out.println("nf : " + nf.getRoundingMode());
System.out.println("BigDecimal is " + new BigDecimal(num).toString());
System.out.println("num after number format : " + nf.format(num));
}
这是显示的实际结果:
nf : HALF_EVEN
num : 16.34625
BigDecimal is 16.346250000000001278976924368180334568023681640625
num after number format : 16.3463
但是,我希望它被四舍五入到 16.3462,因为在 HALF_EVEN 模式下,被丢弃的数字左边的数字是偶数,所以它应该充当 HALF_DOWN。
这是支持此操作的 java 文档 (https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html#HALF_EVEN)。
【问题讨论】:
-
使用 HALF_EVEN 舍入时,它会舍入到最近的偶数 如果它与两个邻居的距离相等。但是 16.346250000000001278976924368180334568023681640625 比 16.3462 更接近 16.3463。你有一个事实,浮点数和双精度数不能准确地表示十进制数,这要感谢。尝试从您的数字的字符串表示形式(即“16.34625”)创建 BigDecimal 以获得所需的行为。
-
只需将
double num = 16.34625;替换为String num = "16.34625";,看看会发生什么…… -
对不起,我还是有点困惑。我同意双 16.34625 的最接近表示是 16.346250000000001278976924368180334568023681640625。但是,由于小数点后的第5位是等距的'5',那么由于它的前一位是偶数的'4',它应该充当half_down,最终结果应该是16.3462。如果前面的数字是奇数,那么它应该作为 half_up。不对吗?