我有一个输入两个double
值的方法。尝试将它们添加到一起时,我会在某个阈值上获得不正确的值,因此我开始使用BigDecimal
。
但即使使用BigDecimal
,我的值仍然不正确吗?
double value1 = 2789.45;
double value2 = 557.89;
System.out.println(BigDecimal.valueOf(value1 + value2));
打印
3347.3399999999997
什么时候应该读作
3347.34
即使value1
和value2
可能高于当前范围,我该如何正确执行此操作? (它们以单独的方法计算)。
我应该使用四舍五入吗?
答案 0 :(得分:8)
我应该使用四舍五入吗?
NOPE ,您所遇到的是double
总和的精度损失。
您首先将双打(value1 + value2
)和将双精度(精度损失)转换为BigDecimal
之后进行求和。
为避免这种情况,请改为使用:
double value1 = 2789.45;
double value2 = 557.89;
System.out.println(BigDecimal.valueOf(value1).add(BigDecimal.valueOf(value2)));
输出:
3347.34
<强>更新强>
-1。您应该从一开始就使用
BigDecimal.valueOf
,而不是使用仍然很脆弱的BigDecimal
,并使用new BigDecimal("2789.45")
,new BigDecimal("557.89")
创建它们。一旦你使用了double
字面值,你就引入了不精确的东西。BigDecimal.valueOf
尝试将其恢复,但并不总是有效。 -Louis Wasserman
其实我并不完全同意这一点。您不能对创建新小数的值进行硬编码,我可以同意直接在String
中读取值(如果可能的话)以避免double
精度丢失:
String value1 = "2789.45";
BigDecimal one = new BigDecimal(value1);
String value2 = "557.89";
BigDecimal two = new BigDecimal(value2);
System.out.println(one.add(two));
输出:
3347.34
这样可以避免Louis Wasserman
注意到的问题。
新工作演示
答案 1 :(得分:1)
因为编译器会首先计算总和,所以它首先添加两个doubles
,因此你会失去精度,你基本上就是这样做了
double value1 = 2789.45;
double value2 = 557.89;
double sum = value1 + value2; // precision lost here
System.out.println(BigDecimal.valueOf(sum));
答案 2 :(得分:1)
将变量分配给双精度时,您已经失去了精度。
考虑这个程序:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
System.out.println(new BigDecimal(2789.45));
System.out.println(new BigDecimal("2789.45"));
}
}
输出:
2789.4499999999998181010596454143524169921875
2789.45
在BigDecimal中执行添加将获得输入的确切总和,但如果您首先转换为double
,则输入将是您写入的值的最接近的双倍。