理解圆半甚至?

时间:2017-11-27 08:02:27

标签: java groovy rounding

当我打印

(new BigDecimal(5) * new BigDecimal(0.049))​

它给出了

0.24500000000000000943689570931383059360086917877197265625

当我使用ROUND_HALF_EVEN

进行舍入时
(new BigDecimal(5) * new BigDecimal(0.049)).setScale(2, BigDecimal.ROUND_HALF_EVEN)​

打印

0.25

所以我的困惑是,它不应该是偶数,所以代替0.25不应该是0.24。请帮助解决这个困惑。谢谢!

2 个答案:

答案 0 :(得分:8)

这里的真正问题是你使用了BigDecimal的错误构造函数。

(new BigDecimal(5).multiply(new BigDecimal("0.049"))).setScale(2, BigDecimal.ROUND_HALF_EVEN)​

会做你想要的。

问题是0.049是浮点文字,并且该值不能完全表示为浮点值(floatdouble),引入了一个微小的错误,在这种情况下是有意义的。

通过使用接受String参数的构造函数,您可以避免通过浮点转换并获得您想要的确切值。

由于精度有限,计算机上的浮点运算充满了令人讨厌的意外行为。如果您想了解有关陷阱的更多信息,请阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic

示例:

public static void main(String[] args) {
    BigDecimal result1 = (new BigDecimal(5).multiply(new BigDecimal("0.049"))).setScale(2, BigDecimal.ROUND_HALF_EVEN);
    BigDecimal result2 = (new BigDecimal(5).multiply(new BigDecimal(0.049))).setScale(2, BigDecimal.ROUND_HALF_EVEN);
    System.out.println(result1);
    System.out.println(result2);
}

打印

0.24
0.25

答案 1 :(得分:4)

  

int java.math.BigDecimal.ROUND_HALF_EVEN:6 [0x6]

     

舍入模式以绕过最近邻居"除非两个邻居都是等距的,在这种情况下,朝着偶数邻居转。

0.24500000000000000943689570931383059360086917877197265625更接近0.25而不是0.24。只选择偶数邻居是两个邻居的距离相等(即如果你试图绕0.245)。

BigDecimal bd = new BigDecimal("0.245").setScale(2, BigDecimal.ROUND_HALF_EVEN);
System.out.println (bd);

将打印0.24