使用Java BigDecimal仍然没有正确解决

时间:2015-10-30 11:22:50

标签: java math double bigdecimal

我有一个输入两个double值的方法。尝试将它们添加到一起时,我会在某个阈值上获得不正确的值,因此我开始使用BigDecimal

但即使使用BigDecimal,我的值仍然不正确吗?

double value1 = 2789.45;
double value2 = 557.89;
System.out.println(BigDecimal.valueOf(value1 + value2));

打印

3347.3399999999997

什么时候应该读作

3347.34

即使value1value2可能高于当前范围,我该如何正确执行此操作? (它们以单独的方法计算)。

我应该使用四舍五入吗?

3 个答案:

答案 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

工作IDEONE DEMO here

<强>更新

  

-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,则输入将是您写入的值的最接近的双倍。