java - java.math.RoundingMode 是如何工作的?

标签 java rounding

我在四舍五入时遇到问题。具体来说,在阅读了所有 javadoc 之后,我期待以下代码:

int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()

返回 n + 0.56。相反,这些是 n04 的返回值:

 new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
 0.56
 new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
 1.55
 new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
 2.56
 new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
 3.56
 new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
 4.55

我也试过改变舍入模式:

int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()

期望 n + 0.55 作为每个 n 的结果。相反,返回值与前面的示例完全相同:

 new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
 0.56
 new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
 1.55
 new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
 2.56
 new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
 3.56
 new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
 4.55

我错过了什么吗?

最佳答案

你遇到的问题是 double 不是一个精确的表示,你是基于这个不精确的数字进行舍入的。

BigDecimal bd = new BigDecimal(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);

打印

bd=1.5549999999999999378275106209912337362766265869140625
after rounding bd=1.55
after rounding d=1.55

不过

BigDecimal bd = BigDecimal.valueOf(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);

打印

bd=1.555
after rounding bd=1.56
after rounding d=1.56

这是有效的,因为 BigDecimal.valueOf 根据打印时 double 的显示方式做了一些额外的舍入。


但是,除非性能/简单性不是问题,否则我不会使用 BigDecimal。

double d = 1.555d;
System.out.println("d=" + d);
d = roundToTwoPlaces(d);
System.out.println("after rounding d=" + d);

public static double roundToTwoPlaces(double d) {
    return ((long) (d < 0 ? d * 100 - 0.5 : d * 100 + 0.5)) / 100.0;
}

打印

d=1.555
after rounding d=1.56

更多详情 Double your money again比较不同舍入方式的性能。

关于java - java.math.RoundingMode 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7124448/

相关文章:

java - Java 编程新手

java - 自定义 Spring Data JPA 构造函数异常

javascript - 如何舍入 Javascript x 和 y 坐标的值

mysql 小数点四舍五入

Python:如何将数字向下舍入到下一个 1000

Java Spring从html表单获取数据

java - 属性文件未反射(reflect)使用 Apache Commons Configuration 修改的更改

java - String[] 和 String 之间的区别

c# - Math.Round 返回奇数向上舍入但偶数向下舍入

iphone - 如何将应用程序图标的角变成圆角