如何检测浮点加法和乘法舍入导致的精度损失?
How can I detect lost of precision due to rounding in both floating point addition and multiplication?
来自计算机系统:程序员的视角:
With single-precision floating point
the expression (3.14f+1e10f)-1e10f
evaluates to 0.0: the value 3.14 is lost due to rounding.
the expression (1e20f*1e20f)*1e-20f
evaluates to +∞ , while 1e20f*(1e20f*1e-20f)
evaluates to 1e20f
.
如何检测浮点加法和乘法舍入导致的精度损失?
underflow和我描述的问题有什么联系和区别?下溢是否只是由于四舍五入导致精度丢失的一种特殊情况,结果四舍五入为零?
谢谢。
虽然在数学中,实数的加法和乘法是关联运算,但这些运算在对浮点类型执行时 不是 关联的,例如 float
,由于有限的精度和范围扩展。
所以顺序很重要。
考虑到示例,数字 10000000003.14 不能精确表示为 32 位 float
,因此 (3.14f + 1e10f)
的结果将是 等于 到 1e10f
,这是最接近的可表示数字。当然,3.14f + (1e10f - 1e10f)
会变成 3.14f
。
请注意,我使用了 f
后缀,因为在 C 中,表达式 (3.14+1e10)-1e10
涉及 double
文字,因此结果确实是 3.14
(或更多可能类似于 3.14999).
在第二个例子中发生了类似的事情,其中1e20f * 1e20f
已经超出了float
的范围(但不是double
)并且连续乘法没有意义,而(1e20f * 1e-20f)
,它首先在另一个表达式中执行,具有明确定义的结果 (1),连续乘法得出正确答案。
在实践中,有一些注意事项你采取
- 使用更宽的字体。
double
最适合大多数应用程序,除非有其他要求。
- 如果可能,重新排序操作。例如,如果您必须添加许多项并且您 知道 其中一些比其他项小,请先添加这些项,然后再添加其他项。避免相同数量级的数字相减。一般来说,可能有一种比原始方法更准确的代数表达式求值方法(例如霍纳的多项式求值方法)。
- 如果您对问题领域有某种了解,您可能已经知道计算的哪一部分可能有问题值,并在执行计算之前检查这些值是否大于(或小于)某些限制。
- 尽快查看结果。当你已经有一个无穷大的值或 NaN 时,继续计算是没有意义的,或者当你的目标值根本没有被修改时继续迭代。
来自计算机系统:程序员的视角:
With single-precision floating point
the expression
(3.14f+1e10f)-1e10f
evaluates to 0.0: the value 3.14 is lost due to rounding.the expression
(1e20f*1e20f)*1e-20f
evaluates to +∞ , while1e20f*(1e20f*1e-20f)
evaluates to1e20f
.
如何检测浮点加法和乘法舍入导致的精度损失?
underflow和我描述的问题有什么联系和区别?下溢是否只是由于四舍五入导致精度丢失的一种特殊情况,结果四舍五入为零?
谢谢。
虽然在数学中,实数的加法和乘法是关联运算,但这些运算在对浮点类型执行时 不是 关联的,例如 float
,由于有限的精度和范围扩展。
所以顺序很重要。
考虑到示例,数字 10000000003.14 不能精确表示为 32 位 float
,因此 (3.14f + 1e10f)
的结果将是 等于 到 1e10f
,这是最接近的可表示数字。当然,3.14f + (1e10f - 1e10f)
会变成 3.14f
。
请注意,我使用了 f
后缀,因为在 C 中,表达式 (3.14+1e10)-1e10
涉及 double
文字,因此结果确实是 3.14
(或更多可能类似于 3.14999).
在第二个例子中发生了类似的事情,其中1e20f * 1e20f
已经超出了float
的范围(但不是double
)并且连续乘法没有意义,而(1e20f * 1e-20f)
,它首先在另一个表达式中执行,具有明确定义的结果 (1),连续乘法得出正确答案。
在实践中,有一些注意事项你采取
- 使用更宽的字体。
double
最适合大多数应用程序,除非有其他要求。 - 如果可能,重新排序操作。例如,如果您必须添加许多项并且您 知道 其中一些比其他项小,请先添加这些项,然后再添加其他项。避免相同数量级的数字相减。一般来说,可能有一种比原始方法更准确的代数表达式求值方法(例如霍纳的多项式求值方法)。
- 如果您对问题领域有某种了解,您可能已经知道计算的哪一部分可能有问题值,并在执行计算之前检查这些值是否大于(或小于)某些限制。
- 尽快查看结果。当你已经有一个无穷大的值或 NaN 时,继续计算是没有意义的,或者当你的目标值根本没有被修改时继续迭代。