Java 大十进制地板舍入出错
我最近问了一个关于奇怪的java双底舍入的问题,得到了使用大小数的答案,因此尝试了以下代码:Java 大十进制地板舍入出错,java,bigdecimal,rounding,Java,Bigdecimal,Rounding,我最近问了一个关于奇怪的java双底舍入的问题,得到了使用大小数的答案,因此尝试了以下代码: BigDecimal velocity = new BigDecimal(-0.07); BigDecimal afterMultiplyingBy200 = velocity.multiply( new BigDecimal(200.0) ); BigDecimal floored = afterMultiplyingBy200.setScale(0, RoundingMode.FLOOR); Sys
BigDecimal velocity = new BigDecimal(-0.07);
BigDecimal afterMultiplyingBy200 = velocity.multiply( new BigDecimal(200.0) );
BigDecimal floored = afterMultiplyingBy200.setScale(0, RoundingMode.FLOOR);
System.out.println("After multiplication " + afterMultiplyingBy200);
System.out.println("floored value is " + floored);
我得到了以下结果
After multiplication -14.000000000000001332267629550187848508358001708984375000
floored value is -15
似乎即使使用BigDecimal,我也无法得到-0.07乘以200的正确值,我能做些什么来精确得到-14.0吗?问题就在这里:
BigDecimal velocity = new BigDecimal(-0.07);
-0.07
不能精确地表示为双精度
,因此传递给BigDecimal
构造函数的文本值最终与-0.07
略有不同BigDecimal
只需获取该近似值并使用它运行,即可生成您看到的结果
尝试:
你应该看一下,特别是我对这个问题的回答中的
一半
:
当编译或解释代码时,您的“0.1”已被删除
按该格式四舍五入到最接近的数字,这将导致较小的
甚至在计算之前就存在舍入误差
问题是newbigdecimal(-0.07)
使用一个double
文本来初始化BigDecimal
——因此错误仍然会发生。请使用采用字符串的BigDecimal
构造函数。您应该使用,以避免由于使用双精度字符而产生舍入错误:
BigDecimal velocity = new BigDecimal("-0.07");
BigDecimal afterMultiplyingBy200 = velocity.multiply(new BigDecimal("200"));
重点矿井的Javadoc摘录:
此构造函数的结果可能有些不可预测。可以假设,在Java中编写新的BigDecimal(0.1)会创建一个完全等于0.1的BigDecimal(无标度值1,标度为1),但实际上等于0.10000000000000055115123125782702118158340451015625。这是因为0.1不能精确地表示为双精度(或者,就此而言,表示为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管如此
另一方面,字符串构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个完全等于0.1的BigDecimal,正如人们所期望的那样。因此,通常建议优先使用字符串构造函数李>
根据,ROUND\u FLOOR
向负无穷大方向旋转,从而将-14.000…
四舍五入到-15
如果您将问题从四舍五入问题更改为乘法问题,为什么要保留错误的标题?
BigDecimal velocity = new BigDecimal("-0.07");
BigDecimal afterMultiplyingBy200 = velocity.multiply(new BigDecimal("200"));