代码之家  ›  专栏  ›  技术社区  ›  Dan Bryant

干净地处理舍入/累加错误

  •  6
  • Dan Bryant  · 技术社区  · 13 年前

    我有一个应用程序,我正在跟踪L中的流体体积。我目前正在使用“double”来存储整个系统中的体积,在大多数情况下,这都很好。然而,当我开始对这些体积进行大量加减时,各种累积误差开始悄悄出现。这些误差的幅度很小,但它们会导致阈值比较出现问题,体积突然比预期小了一小部分,导致验证失败。我知道这是执行累积浮点运算时相当常见的问题,但我想知道如何最好地解决这些问题。我有几个想法:

    1. 我可以用整数替换所有的双引用,而不是跟踪nL中的所有内容。这肯定会解决问题,但这是一个非常侵入性的更改。然而,该系统尚未投入生产使用,这意味着现在应用它将比以后尝试应用它容易得多。

    2. 我可以用小数代替双精度。这比更改为整数侵入性更小,但仍然需要进行相当大的更改。

    3. 我可以要求所有体积比较都允许指定的误差容限。这主要是我现在正在做的,但这会使比较代码变得更丑陋,并且需要进行一些代码审查,以确保没有人忘记应用该模式。

    4. 我可以在每次计算后执行舍入到指定的公差,以防止误差累积。这使得比较更加清晰,但现在它在任何有作业的地方都有类似的问题。

    对于那些也在与这个问题作斗争的人来说,什么解决方案最终是最干净的?在进行累积计算时,我还应该了解其他问题吗?

    1 回复  |  直到 13 年前
        1
  •  2
  •   Mike Sherrill 'Cat Recall'    13 年前

    理想情况下,您希望

    • 使用不受舍入(近似)误差影响的数据类型,以及
    • 四舍五入到小数位数
    • 在正确的时间。

    你不需要大范围的双精度浮子。你 可能 不想使用整数。它们稍微快一点,但使用起来更复杂。使用数字或十进制。数字和十进制数据类型既不会出现舍入误差,也不会出现近似误差。但在编程时,你仍然不能粗心大意;给double类型的变量指定一个数值会让你重新想到这个问题。

    到底是什么 小数位数正确 合适的时间 平均值取决于您的应用程序。正确的小数位数有时可能超过您需要存储为最终值的位数。正确的时间可能会受到中间计算的数量和性质的影响。

    有时候,人们怎么称呼 舍入误差 真的 近似误差 。如果你告诉你的计算机存储十进制值 r 在浮点变量或数据库列中,它实际上将存储最接近的浮点近似值 r .

    Canonical reference for FP arithmetic

    推荐文章