BigDecimal bd1 = new BigDecimal(1.245);
System.out.println(">> Half up: "
+ bd1.setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println(">> Half down: "
+ bd1.setScale(2, BigDecimal.ROUND_HALF_DOWN));
结果:
一半:1.25
半场:1.25
答案 0 :(得分:4)
这是构造函数中初始double的结果。如果你这样做
BigDecimal bd1 = new BigDecimal("1.245");
(即带引号)它会按预期工作。
双值1.245
无法准确表示,实际上是1.24500000000000010658141036401502788066864013671875
,因此它太大而无法实际舍入“向下”。
答案 1 :(得分:3)
如果您打印原始值,您将看到:
1.24500000000000010658141036401502788066864013671875
这是因为1.245不能表示为双号
现在阅读有关setScale ROUND_HALF_DOWN
的文档舍入模式向"最近邻居"除非两者 邻居是等距的,在这种情况下向下舍入。表现为 ROUND_UP,如果丢弃的分数> 0.5 强>;否则,表现得像 ROUND_DOWN。
如您所见,丢弃的分数> 0.5,与预期不相等
如果您将初始变量声明为BigDecimal bd1 = new BigDecimal("1.245");
,则会获得预期结果
答案 2 :(得分:2)
我认为这是因为您使用了float
的构造函数,它会将您的值转换为1.2456345
,请尝试:
BigDecimal bd1 = new BigDecimal("1.245");
答案 3 :(得分:1)
问题来自浮动。你应该知道使用float和double,你永远不会得到精确的值。像0.1不等于1/10。
如果您对高精度感兴趣,则必须使用BigDecimal,但要将其与字符串值一起使用,这样您就不会因浮动投射而失去预备。
将您的代码更改为:
BigDecimal bd1 = new BigDecimal("1.245");
答案 4 :(得分:1)
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
你可以看到“注意:对于float和double NaN以及±Infinity以外的值,这个构造函数与Float.toString(float)和Double.toString(double)返回的值兼容。这通常是首选将float或double转换为BigDecimal的方法,因为它不会受到BigDecimal(double)构造函数的不可预测性的影响。“
所以,如果你想用浮点数设置一个BigDecimal,你应该
BigDecimal bd1 = new BigDecimal(Float.toString(1.245f));
您还可以查看构造函数的注释 public BigDecimal(double val)
另一方面,String构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个BigDecimal,它正好等于0.1,正如人们所期望的那样。因此,通常建议首先使用String构造函数。
当必须将double用作BigDecimal的源时,请注意此构造函数提供了精确的转换;它不会产生与使用Double.toString(double)方法将double转换为String然后使用BigDecimal(String)构造函数相同的结果。要获得该结果,请使用static valueOf(double)方法。