2012-03-28 84 views
10

我的同事做了这个实验:双减法精度问题

public class DoubleDemo { 

     public static void main(String[] args) { 
      double a = 1.435; 
      double b = 1.43; 
      double c = a - b; 
      System.out.println(c); 
     } 
} 

对于这个一年级的操作我预计这样的输出:

0.005 

但没想到的产量为:

0.0050000000000001155 

为什么double在这么简单的操作中失败?如果double不是这项工作的数据类型,我应该使用什么?

+0

感谢您分享您的实验。 +1 – kasavbere 2012-03-28 15:46:13

+0

我敢肯定,这是[保留精度双打在Java]重复 – 2012-03-28 15:47:17

+0

可能重复(http://stackoverflow.com/questions/322749/retain-precision-with-doubles-in-java) – 2012-03-28 15:49:23

回答

17

double在内部存储为一个分数在二进制 - 像1/4 + 1/8 + 1/16 + ...

0.005 - 或值1.435 - 不能被存储为确切小数二进制,所以double不能存储的确切值为0.005,减法值不完全确切。

如果您关心精确的十进制算术,请使用BigDecimal

您还可能会发现this article有用的阅读。

+0

+ 1使用BigDecimal或舍入结果。 – 2012-03-28 17:59:12

2

double和float是不完全是实数

在任何范围内都有无数的实数,但只有有限的位数来表示它们!由于这个原因,双精度和浮点数预计会有舍入误差。

您得到的数字是可能的最接近的数字,可以用浮点表示中的double来表示。

有关更多详细信息,您可能需要阅读this article [警告:可能是高级别]。

您可能希望使用BigDecimal来得到完整的十进制数[但当您尝试获取1/3时,您将再次遇到舍入错误。

1

doublefloat由于发生在“引擎盖下”的四舍五入,算术运算永远不会是完全正确的。

基本上双打和浮动可以有无限的小数,但在内存中它们必须由一些实数位表示。所以,当你做这个十进制算术时,会发生一个舍入过程,如果你考虑所有的小数,通常会被忽略。

正如前面所说,如果你需要完全精确的值,则使用BigDecimal其不同存储其值。 Here's the API

+0

说他们“永不”完全正确是不准确的。说分母不是2的幂的分数以外的其他分数时,它们绝不会是完全正确的。 – supercat 2015-02-15 17:36:53

-1
//just try to make a quick example to make b to have the same precision as a has, by using BigDecimal 

private double getDesiredPrecision(Double a, Double b){ 
    String[] splitter = a.toString().split("\\."); 
    splitter[0].length(); // Before Decimal Count 
    int numDecimals = splitter[1].length(); //After Decimal Count 

    BigDecimal bBigDecimal = new BigDecimal(b); 
    bBigDecimal = bBigDecimal.setScale(numDecimals,BigDecimal.ROUND_HALF_EVEN); 

    return bBigDecimal.doubleValue(); 
} 
+0

这并没有回答这个问题。 – 2014-08-15 14:08:27

+0

好吧,你是对的。试着在BigDecimal上做一些小例子。已经有人回答这个问题。不需要重复。 – madmaximshen 2014-08-15 15:21:43

+0

在SO上,答案是提供一个完整的,自包含的答案。如果您觉得在其他答案中缺少某些内容,请在您拥有足够的信誉后留下评论。如果你认为你可以写一个更好的*完整*答案,那么做。不要发布这样的“半答案”。 – 2014-08-15 15:27:26