这是使用 BigDecimals 舍入的正确行为吗?
Is this the correct behavior for rounding with BigDecimals?
我试图像这样舍入 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吗,还是我理解错了什么?
使用 ROUND_HALF_DOWN
使用 BigDecimal
进行舍入在 JavaDoc 中定义为“ROUND_HALF_DOWN - 舍入模式向 "nearest neighbor" 舍入,除非两个邻居是等距的,在这种情况下向下舍入。" Documentation ROUND_HALF_DOWN Documentation RoundingMode.HALF_DOWN
对于 BigDecimal.valueOf("5.46597").setScale(2, BigDecimal.ROUND_HALF_DOWN)
,最近的邻居是 5.46
和 5.47
,距离为 0.00597
和 0.00403
。
所以到 5.47
的距离比到 5.46
的距离更小(更近),这导致四舍五入到 5.47
.
HALF_DOWN 仅当实际值恰好位于两个可能的舍入值的中间时才向下舍入。 IE。 5.46500 -> 5.46。另一方面,5.4650000001 -> 5.47,因为它比 5.46 更接近 5.47。
也许您要查找的是 RoundingMode.DOWN
,它总是向下舍入。
第一:使用double值的构造函数,立即引入每个浮点数的逼近误差
正在使用
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 边界。
Logical rounding will happen to its nearest integer, above a half will be rounded up, below a half will round be rounded down. On the exact half the international math standard says: round up, but logically (the same distance) it can be either: HALF_UP or HALF_DOWN. As the effect only relates to the exact half, testing should not be done with a double constructor, that probably yields a value a tiny bit above or below the exact half.
你也忘记了作业
当截断部分 > 0.5 时,RoundingMode.HALF_DOWN 和 RoundingMode.HALF_UP 的工作方式相同,例如这里,
BigDecimal bD = new BigDecimal(5.46597);
bD.setScale(2, RoundingMode.HALF_DOWN);//5.47
bD.setScale(2, RoundingMode.HALF_UP; //5.47
因为小数点后2位截断部分(597)->0.597大于0.5。
这就是 HALF_DOWN
规范所说的
"Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round down. Behaves as for
RoundingMode.UP if the discarded fraction is > 0.5; otherwise, behaves
as for RoundingMode.DOWN."
如果您的需求如下
BigDecimal bD = new BigDecimal(5.46597);
bD.setScale(2, RoundingMode.HALF_DOWN);//5.46
然后使用@Balázs Sipos 自己建议的下面一行。
bD.setScale(3, RoundingMode.DOWN).setScale(2, RoundingMode.HALF_DOWN);
//first part would give 5.465 then the second part would produce 5.46
应该可以。干杯!
我试图像这样舍入 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吗,还是我理解错了什么?
使用 ROUND_HALF_DOWN
使用 BigDecimal
进行舍入在 JavaDoc 中定义为“ROUND_HALF_DOWN - 舍入模式向 "nearest neighbor" 舍入,除非两个邻居是等距的,在这种情况下向下舍入。" Documentation ROUND_HALF_DOWN Documentation RoundingMode.HALF_DOWN
对于 BigDecimal.valueOf("5.46597").setScale(2, BigDecimal.ROUND_HALF_DOWN)
,最近的邻居是 5.46
和 5.47
,距离为 0.00597
和 0.00403
。
所以到 5.47
的距离比到 5.46
的距离更小(更近),这导致四舍五入到 5.47
.
HALF_DOWN 仅当实际值恰好位于两个可能的舍入值的中间时才向下舍入。 IE。 5.46500 -> 5.46。另一方面,5.4650000001 -> 5.47,因为它比 5.46 更接近 5.47。
也许您要查找的是 RoundingMode.DOWN
,它总是向下舍入。
第一:使用double值的构造函数,立即引入每个浮点数的逼近误差
正在使用
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 边界。
Logical rounding will happen to its nearest integer, above a half will be rounded up, below a half will round be rounded down. On the exact half the international math standard says: round up, but logically (the same distance) it can be either: HALF_UP or HALF_DOWN. As the effect only relates to the exact half, testing should not be done with a double constructor, that probably yields a value a tiny bit above or below the exact half.
你也忘记了作业
RoundingMode.HALF_DOWN 和 RoundingMode.HALF_UP 的工作方式相同,例如这里,
BigDecimal bD = new BigDecimal(5.46597);
bD.setScale(2, RoundingMode.HALF_DOWN);//5.47
bD.setScale(2, RoundingMode.HALF_UP; //5.47
因为小数点后2位截断部分(597)->0.597大于0.5。 这就是 HALF_DOWN
规范所说的"Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. Behaves as for RoundingMode.UP if the discarded fraction is > 0.5; otherwise, behaves as for RoundingMode.DOWN."
如果您的需求如下
BigDecimal bD = new BigDecimal(5.46597);
bD.setScale(2, RoundingMode.HALF_DOWN);//5.46
然后使用@Balázs Sipos 自己建议的下面一行。
bD.setScale(3, RoundingMode.DOWN).setScale(2, RoundingMode.HALF_DOWN);
//first part would give 5.465 then the second part would produce 5.46
应该可以。干杯!