3

我正在开发一些工具来计算在最坏情况下可以接近的数字1e-25,并在 Java 中将它们一起比较。我显然使用双精度。

我在另一个答案1e-15中读到,我不应该期望超过1e-17精度,而另一个问题涉及在以“更好”的顺序排序操作时获得更好的精度。

哪些双精度操作更热衷于在此过程中降低精度?我应该尝试使用尽可能大的数字还是尽可能小的数字?在乘法之前先做除法吗?

我宁愿不使用BigDecimal类或等价物,因为代码已经足够慢了;)(当然,除非它们不会对速度产生太大影响)。

任何信息将不胜感激!

编辑:数字在绝对值(1e-25)中“小”的事实并不重要,因为 double 可以下降到 1e-324。但重要的是,当它们非常相似时(都在 1e-25 中),我必须比较,比如说 4.64563824048517606458e-21 和 4.64563824048517606472e-21(差异是第 19 位和第 20 位)。在计算这些数字时,差异是如此之小,以至于我可能会遇到“舍入误差”,其中余数被随机数填充。

问题是:“如何对计算进行排序以使这种精度损失最小化?”。它可能在乘法之前先进行除法,或者先进行加法。

4

2 回答 2

3

如果获得正确答案很重要,则应使用 BigDecimal。它比 double 慢,但在大多数情况下它已经足够快了。我想不出在很多情况下,你用这么小的数字进行大量计算,而答案是否正确并不重要——至少对于 Java。

如果这是一个超级性能敏感的应用程序,我会考虑使用不同的语言。

于 2013-06-15T06:41:57.403 回答
1

感谢@John 指出了一篇关于浮点运算的非常完整的文章。

事实证明,当需要精度时,应该重新排序运算,并调整公式以避免精度损失,如取消章节中所述:当比较彼此非常接近的数字时(这是我的情况),可能会发生“灾难性取消”,从而导致精度的巨大损失。通常,根据您对操作数值的先验知识重新编写公式或重新排序运算可以提高微积分的准确性。

我将从这篇文章中记住的是:

  • 减去两个几乎相同的量时要小心
  • 尝试重新安排操作以避免灾难性取消

对于后一种情况,请记住计算(x - y) * (x + y)给出的结果比x * x - y * y.

于 2013-06-20T05:05:54.807 回答