Rus*_*kov 2 java rounding bigdecimal
我最近问一个关于奇怪的java双层舍入的问题,并得到了使用BigDecimals的答案,所以尝试了以下代码:
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);
Run Code Online (Sandbox Code Playgroud)
而且我得到了以下结果
After multiplication -14.000000000000001332267629550187848508358001708984375000
floored value is -15
Run Code Online (Sandbox Code Playgroud)
似乎即使使用BigDecimal我也无法得到正确的值 - 将-0.07乘以200,我能做些什么来准确得到-14.0?
从我对这个问题的回答:
编译或解释代码时,"0.1"已经四舍五入到该格式中最接近的数字,即使在计算发生之前也会导致小的舍入误差.
问题是new BigDecimal(-0.07);使用double文字初始化BigDecimal- 所以错误仍然发生.使用取代的BigDecimal构造函数String.
您应该使用字符串构造函数来避免由于使用双精度数而导致的舍入错误:
BigDecimal velocity = new BigDecimal("-0.07");
BigDecimal afterMultiplyingBy200 = velocity.multiply(new BigDecimal("200"));
Run Code Online (Sandbox Code Playgroud)
使用双精度数的构造函数的 Javadoc 摘录- 重点是我的:
- 此构造函数的结果可能有些不可预测。人们可能会认为在 Java 中编写 new BigDecimal(0.1) 会创建一个恰好等于 0.1(未缩放的值 1,小数位数为 1)的 BigDecimal,但它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 不能精确地表示为 double(或者就此而言,表示为任何有限长度的二进制分数)。因此,无论表面如何,传递给构造函数的值并不完全等于 0.1。
- 另一方面,String 构造函数是完全可以预测的:编写 new BigDecimal("0.1") 会创建一个恰好等于 0.1 的 BigDecimal,正如人们所期望的那样。因此,一般建议优先使用 String 构造函数而不是这个。
| 归档时间: |
|
| 查看次数: |
8104 次 |
| 最近记录: |