【问题标题】:Getting wrong answer in double arithmetic in Java [duplicate]在Java中的双重算术中得到错误的答案[重复]
【发布时间】:2013-01-06 23:38:45
【问题描述】:

可能重复:
Double calculation producing odd result

我正在用 Java 编写一个程序来处理大量的双重算术。我最终到了需要添加 0.6666666666666666 和 -0.666666666666667 的地步。但是,我得到的答案是 -3.3306690738754696E-16。

换句话说,

double d1 = 0.6666666666666666;
double d2 = -0.666666666666667;
System.out.println(d1 + d2);

打印出“-3.3306690738754696E-16”。为什么会这样?

提前谢谢你。

【问题讨论】:

标签: java math floating-point double


【解决方案1】:

doubles 并不完全准确,而且并非每个小数都可以完美地表示为 double(请参阅 this)。出于所有实际目的,-3.3306690738754696E-160 *。但是,如果您需要更高的精度,请使用BigDecimal。请记住,这种替代方法的效率不如使用原始 doubles 的效率高。您可以自行决定是否需要此级别的准确度并做出相应的选择。

*:显然,这个数字并不完全为零,但对于大多数现实世界的计算和计算,一个 小的值将是微不足道的。以米为单位,这个值小于质子和中子的直径——即非常非常小。这就是我所说的“出于所有实际目的”。

【讨论】:

  • 仅出于教育目的,您能解释一下为什么您说 -3.3306690738754696E-16 对于所有实际目的都是 0 吗?这个怎么可能?感谢您对 BigDecimals 的建议
  • @fpele:你认为 -3.3306690738754696E-16 有多大?你看过双数表示吗?你熟悉科学记数法吗?你查过什么吗?
  • 我的错,我以为答案是 E+16。不过没必要粗鲁。
  • @fpele:我很惊讶,仅此而已。
【解决方案2】:

double 值不能精确地表示所有值,这就是一个例子。您可以改用BigDecimal

BigDecimal bd1 = new BigDecimal("0.6666666666666666");
BigDecimal bd2 = new BigDecimal("-0.666666666666667");
System.out.println(bd1.add(bd2));

输出:

-4E-16

【讨论】:

  • 有趣的是,我一直认为双精度数是浮点运算的终极解决方案。非常感谢!
  • @fpele double 仍然在当前 CPU 上实现高效浮点的终极解决方案。 BigDecimal 是定点类型,不是浮动的。
  • @us2012:你确定吗?对我来说,它看起来很像浮点数。例如,一个产品的scale通常是被乘数的比例之和;使用固定点,我希望结果与输入具有相同的比例。
  • @MarkDickinson 你说得对,我把术语弄混了。我试图说明的一点是,BigDecimal 不像我们期望的浮点数那样表现。正确的术语当然是任意精度,这会带来巨大的性能成本,因此只要您不明确需要任意精度,double 仍然是最佳解决方案。
  • @us2012: 真的……
猜你喜欢
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多