这是使用BigDecimals舍入的正确行为吗?

时间:2019-04-25 14:31:28

标签: java rounding scale bigdecimal

我正在尝试对这样的BigDecimals进行四舍五入:5.46597-> 5.46,我认为下面的代码对我有用,但是不能。

我用BigDecimal.round和BigDecimal.setScale尝试过。

BigDecimal bD = new BigDecimal(5.46597); // whole number: 5.4659700000000004393996277940459549427032470703125 
bD.setScale(2, RoundingMode.HALF_DOWN); // 5.47
bD.round(new MathContext(3, RoundingMode.HALF_DOWN)); // 5.47

这不是5.46,还是我误解了什么?

3 个答案:

答案 0 :(得分:10)

仅当实际值恰好位于两个可能的取整值之间的一半时,HALF_DOWN才向下取整。即5.46500-> 5.46。另一方面是5.4650000001-> 5.47,因为它比5.46更接近5.47。

也许您正在寻找的是RoundingMode.DOWN,它总是四舍五入。

答案 1 :(得分:4)

使用BigDecimal进行ROUND_HALF_DOWN舍入在JavaDoc中定义为“ ROUND_HALF_DOWN-舍入模式向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下舍入。 em>“ Documentation ROUND_HALF_DOWN Documentation RoundingMode.HALF_DOWN

对于BigDecimal.valueOf("5.46597").setScale(2, BigDecimal.ROUND_HALF_DOWN),最近的邻居是5.465.47,距离为0.005970.00403。 因此,到5.47的距离(更近)比到5.46的距离更近(这导致四舍五入到5.47

答案 2 :(得分:2)

首先:使用具有双精度值的构造函数,立即引入每个浮点的近似误差。

使用

BigDecimal bD = new BigDecimal("5.46597");
bD = bD.setScale(2, RoundingMode.HALF_DOWN); // 5.47

BigDecimal bD = new BigDecimal("5.46500");
bD = bD.setScale(2, RoundingMode.HALF_DOWN); // 5.46

一个精确的定点数带有5个小数。

HALF_DOWN向下舍入为.500000 ...再也没有分数,只有5er边界。

  

逻辑舍入将发生到最接近的整数,大于一半将被舍入,小于一半将被舍入。在精确一半上,国际数学标准说:向上取整,但在逻辑上(相同的距离)可以是:HALF_UP或HALF_DOWN。由于效果 only 仅与精确一半有关,因此不应使用double构造函数进行测试,它可能会产生一个值,该值略高于或低于精确一半。

您还忘记了作业。