从计算机系统:程序员的角度:
单精度浮点
表达式
的计算结果为 0.0:值 3.14 由于舍入而丢失。(3.14f+1e10f)-1e10f
表达式
的计算结果为 +∞ ,而(1e20f*1e20f)*1e-20f
的计算结果为1e20f*(1e20f*1e-20f)
。1e20f
如何检测由于浮点加法和乘法舍入而导致的精度损失?
下溢和我描述的问题有什么联系和区别?下溢是否只是由于舍入而导致精度损失的一种特殊情况,即结果舍入为零?
虽然在数学中,实数的加法和乘法是关联运算,但由于精度和范围扩展有限,这些运算在浮点类型上执行时是不是关联的,例如
float
。
所以顺序很重要。
考虑到这些示例,数字 10000000003.14 无法精确表示为 32 位
float
,因此 (3.14f + 1e10f)
的结果将是 equal 到 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
最适合大多数应用,除非有其他要求。