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

时间:2013-02-25 17:55:42

标签: c# .net rounding

我有一个应用程序,我用μL跟踪流体体积。我目前正在使用'double'来存储整个系统中的卷,这在大多数情况下都可以正常工作。然而,当我开始添加和减去大量的这些卷时,各种累积错误开始蔓延。错误的幅度非常小,但它们会导致阈值比较出现问题,突然体积小于预期的微小量,导致验证失败。我理解这是执行累积浮点运算的一个相当常见的问题,但我想知道如何最好地解决这些问题。我有一些想法:

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

  2. 我可以使用Decimal而不是double。这比改为整数的侵入性小,但仍然需要相当大的改变。

  3. 我可以要求所有卷比较都允许指定的容错。这主要是我现在正在做的事情,但它使比较代码更加丑陋,需要进行一些代码审查,以确保没有人忘记应用该模式。

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

  5. 对于那些也在努力解决这个问题的人来说,最简洁的解决办法是什么呢?在进行累积计算时是否还有其他问题需要了解?

1 个答案:

答案 0 :(得分:2)

理想情况下,你想要

  • 使用不受舍入(近似)错误的数据类型和
  • 舍入到正确的小数位数
  • 在合适的时间。

您不需要大范围的双精度浮点数。您可能不想使用整数。它们稍微快一点,但使用它们会更复杂。使用数字或小数。数字和十进制数据类型不受舍入误差或近似误差的影响。但是你仍然不能在编程中粗心大意或草率;将数值赋给double类型的变量会将问题带回给您。

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

有时,人们称之为舍入错误的确是近似错误。如果您告诉计算机将十进制值 r 存储在浮点变量或数据库列中,它实际上会将最接近的浮点近似值存储到 r

Canonical reference for FP arithmetic