【问题标题】:Rounding error for double? [duplicate]双舍入误差? [复制]
【发布时间】:2014-11-22 17:59:30
【问题描述】:

当我运行以下代码时:

double x = 4.35;
double y = x * 100;
System.out.println(y);

我得到434.99999999999994,由于浮点精度的性质,这是预期的。但是当我运行时:

double x = 4.35;
double y = x * 1000;
System.out.println(y);

我在控制台中得到4350.0。同样,当我用10 替换1000 时,我得到43.5,这很奇怪,因为这些数字没有舍入误差。当我将双倍乘以10 to the power of the number of decimal places 时,似乎只有舍入误差。为什么会这样?

另外,当我尝试使用4.25 作为x 的值运行这三个代码块时,我在控制台中得到了一个不错的425.0。舍入误差是否只适用于某些十进​​制值?

编辑: 4.35 除以 10 也给了我一个古怪的小数(确切地说是0.43499999999999994)。此外,如果我将 x 设置为 43.5,则根本没有舍入误差。乘以 10 得到 435.0。

编辑 2: 我认为有些人误解了我的问题。我在问为什么会发生这种情况,不是如何避免遇到这些错误。

【问题讨论】:

  • 有趣的是,当我使用 float 时,我得到的是 435.0。
  • 原因在于在您使用的特定 CPU 中实现计算的方式。 en.wikipedia.org/wiki/Floating-point_unit
  • @JimGarrison 该文档仅在对“天哪,这很复杂,我最好将浮点错误视为随机错误”的答案感到满意时才直接回答这个问题,只要一个就可以了记得一个人正在做一个抽象。如果一个人不太容易满足,那么您链接到的文档只会回答问题,就像 Java 语言定义回答 StackOverflow 上的大多数 Java 问题一样。
  • 您可以看到使用 BigDecimal 的确切值,这将解释一些值按预期四舍五入的方式,而一些值应该是一个小错误。

标签: java floating-point double floating-point-precision


【解决方案1】:

不产生任何舍入误差的计算是可以在二进制系统中精确表示的计算。这包括所有整数,例如,十进制 0.5,即 0.1 二进制或 0.25 十进制,即 0.01 二进制。因此,您发布的示例没有舍入错误。 0.35 十进制但是不能用有限多个二进制数字表示。

【讨论】:

  • 4.35 没有以二进制精确表示。
  • 是的。将其添加到答案中。
【解决方案2】:

没有办法避免浮点运算错误。用于表示数字的位数总是有限的。您所能做的就是使用具有更高精度(位)的数据类型,例如 java.math.BigDecimal。阅读 John Zukowski 的The need for BigDecimal 了解更多信息。 试试这个::

import java.math.BigDecimal;

double x = 4.35;
BigDecimal bd1 = BigDecimal.valueOf(x);
BigDecimal bd2= BigDecimal.valueOf(100);
BigDecimal multiply = bd1.multiply(bd2);
System.out.println(multiply);
猜你喜欢
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多