【问题标题】:Adding and subtracting doubles are giving strange results [duplicate]加减双打会产生奇怪的结果[重复]
【发布时间】:2013-03-15 13:39:03
【问题描述】:

所以当我在 Java 中使用 Doubles 进行加法或减法时,它会给我带来奇怪的结果。以下是一些:

如果我添加0.0 + 5.1,它会给我5.1。没错。

如果我添加5.1 + 0.1,它会给我5.199999999999(重复9s 的次数可能会关闭)。错了。

如果我减去4.8 - 0.4,它会给我4.39999999999995(同样,重复的9s 可能会关闭)。错了。

起初我以为这只是用十进制值添加双精度的问题,但我错了。以下工作正常:

5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8

现在,添加的第一个数字是保存为变量的双精度数,尽管第二个变量从JTextField 中获取文本。例如:

//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999

【问题讨论】:

  • 顺便说一句,更喜欢使用 BigDecimal (docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html)
  • 其实5.19999999...(有无数个重复的9)在数学上和5.2完全一样,如果你不相信,试着找出两者的区别是什么。它是 0,因此它们是相同的。
  • @Ingo 从技术上讲,是的,但我想有一点准确的答案:)
  • Rob,我明白了,我很遗憾这些数字被称为“float”和“double”。适当的名称是“粗略的近似”和“稍微好一点,但仍然是粗略的近似”

标签: java double


【解决方案1】:

在 Java 中,double 的值为 IEEE floating point numbers。除非它们是 2 的幂(或 2 的幂之和,例如 1/8 + 1/4 = 3/8),否则即使它们具有很高的精度,它们也无法精确表示。一些浮点运算会加重这些浮点数中存在的舍入误差。在您上面描述的情况下,浮点错误已经变得严重到足以显示在输出中。

无论数字的来源是什么,无论是从 JTextField 解析字符串还是指定 double 文字 - 问题都在于浮点表示形式的继承。

解决方法:

  • 如果你知道你只有这么多小数点,那就用整数 算术,然后转换为小数:

    (double) (51 + 1) / 10
    (double) (48 - 4) / 10
    
  • 使用BigDecimal

  • 如果你必须使用double,你可以减少浮点错误 与Kahan Summation Algorithm。

【讨论】:

  • 你认为如果我改用floats 会给出更准确的值吗?
  • float 通常只有double 的一半精度。如果您需要精度,这不是一个好主意。
  • @Ingo:很好的收获;我已经更新了我的答案。
【解决方案2】:

在 Java 中,双精度数使用 IEEE 754 浮点算法(请参阅 this 维基百科文章),这本质上是不准确的。使用BigDecimal 获得完美的十进制精度。要在打印中进行四舍五入,仅接受“相当不错”的准确性,请使用printf("%.3f", x)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2012-01-05
    • 2015-10-04
    • 1970-01-01
    • 2015-09-26
    • 2021-07-20
    • 1970-01-01
    相关资源
    最近更新 更多