如何截断BigDecimal而不进行四舍五入

45
在我的代码中进行一系列计算后,我得到了一个值为0.01954的BigDecimal。
现在我需要将这个BigDecimal乘以100,希望最终结果为1.95。
我不想对结果进行任何四舍五入,只希望保留两位小数并截取之后的数值。
我尝试将BigDecimal对象设置为scale为2,但是出现了ArithmeticException异常,提示需要进行四舍五入。如何在不指定四舍五入的情况下设置scale呢?

1
Math.floor(VALUE)将返回一个整数值,那么为什么不这样做:(double)((double)Math.Floor(1.95*100)/(double)100) - Fallenreaper
5个回答

80

new BigDecimal (4343.33).setScale(2, RoundingMode.DOWN) 返回 4343.32。 - user666
4
您正在使用接受浮点数值的构造函数,该值本身可能存在舍入误差。请改用接受String类型参数的构造函数:new BigDecimal("4343.33").setScale(2, RoundingMode.DOWN)。该方式能够避免精度问题。 - GriffeyDog
1
没错,我试过了,它有效。但是如果我已经有一个 BigDecimal 对象呢?它会像字符串一样处理吗? - user666
@San4musa 不是这样的,你会得到 x.55。你可以自己尝试一下:BigDecimal myBigDecimal = new BigDecimal("5.5555555"); BigDecimal newValue = myBigDecimal.setScale(2, RoundingMode.DOWN); System.out.println(newValue); - GriffeyDog
@GriffeyDog 你是对的,我在 HALF_DOWN 上搞错了,我的评论无法编辑所以我删除了它。“如果使用 RoundingMode.DOWN 模式,当值为 x.5555555 时会失败,因为截断值 > 0.5,所以它会四舍五入到 x.56,如果你使用 BigDecimal newValue = myBigDecimal.setScale(2, RoundingMode.DOWN);”这个说法对于 DOWN 模式不正确,只适用于 HALF_DOWN 模式。 - San4musa

13

使用包括RoundingMode的setScale重载方法:

value.setScale(2, RoundingMode.DOWN);

8

当我使用一个BigDecimal设置另一个BigDecimal时,我遇到了截断问题。源可以具有不同的小数值。

BigDecimal source = BigDecimal.valueOf(11.23); // could 11 11.2 11.234 11.20 etc

为了将其正确缩短并标度为两位小数,我不得不使用源的字符串值而不是 BigDecimal 或 double 值。
new BigDecimal(source.toPlainString()).setScale(2, RoundingMode.FLOOR))

我用这个来处理货币,结果总是返回保留两位小数的值。

  • 11 -> 11.00
  • 11.2 -> 11.20
  • 11.234 -> 11.23
  • 11.238 -> 11.23
  • 11.20 -> 11.20

11.238 -> 11.28? - Zbyszek

1

BigDecimal.valueOf(7.777) .setScale(2, RoundingMode.DOWN) .stripTrailingZeros()

结果: 7.77

BigDecimal.valueOf(7.7) .setScale(2, RoundingMode.DOWN) .stripTrailingZeros()

结果: 7.7

BigDecimal.valueOf(77) .setScale(2, RoundingMode.DOWN) .stripTrailingZeros()

结果: 77


0

就我所测试的四舍五入函数并不能解决问题。如果一个值出现了以下情况,该怎么办。

BigDecimal val2 = new BigDecimal(45.9);
System.out.println(val2.setScale(2,RoundingMode.DOWN));

result; 45.89

最好的方法是从 SQL 端进行转换,或编写一个实用函数将其乘以 100 并传递给 Integer,再除以一百并传递给 BigDecimal。
在我的情况下,我使用了:
sql:-  CAST(<VALUE> AS decimal(10,2)). 

你的第一个案例失败是因为你使用了double来创建BigDecimal。此外,你使用setScale来添加小数,这与问题要求相反。 - Zastai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接