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

Dan*_*ant 6 .net c# rounding

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

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

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

  3. 我可以要求所有卷比较都允许指定的容错.这主要是我在做什么,现在,但它使比较难看的代码,它需要一些代码审查,以确保没有人忘记应用模式.

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

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

Mik*_*ll' 2

理想情况下,您想要

  • 使用不受舍入(近似)错误影响的数据类型,并且
  • 四舍五入到小数点后的正确位数
  • 在正确的时间。

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

正确的小数位数正确的时间的确切含义取决于您的应用程序。正确的小数位数有时可能比您需要存储为最终值的位数更多。正确的时间可能会受到中间计算的数量和性质的影响。

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

FP 算法的规范参考