为什么除数下溢仅在除数远小于被除数时引起,无论除数大小如何,分母都足够接近零时不应该发生?
问问题
3588 次
1 回答
3
来自http://www.strw.leidenuiv.nl/docs/intel/f_ug/ieee_ovw.htm
如果舍入结果的指数太小而无法使用结果的浮点格式表示,则会发生下溢异常。
这意味着当被除数和除数的比率小到足以超过浮点格式的精度时,就会发生错误,而不是依赖于特定值(例如 epsilon)。
当分母接近零时,假设分子非零,除法的结果将接近无穷大。当分子接近零时,假设分母非零,结果接近零。当这个值变得足够小时,就会发生。
如果分子和分母的值非常接近,即使它们非常小,也可以获得有用的结果,因此非常小的分子不一定会导致下溢。
示例:
在 C# 中,epsilon 是 1.401298E-45。
ε/ε == 1.0f
即使分子非常非常小,结果仍然是有效的浮点数。
现在,如果你要尝试这样的事情:
float max = 3.40282347E+38f;
/// underflow, denominator will be 0.0f
float denominator = epsilon / max;
denominator
将有 1e-83 的订单。由于 83 远远超过最大单精度浮点指数,该值将被钳制为零。这是发生下溢的地方。
/// generates a divide-by-zero error.
float result = 10 / denominator;
这会生成被零除而不是无穷大,因为存储在 中的中间结果在denominator
用于第二个操作之前首先被钳制为 0。
是下溢还是被零除取决于编译器、您的使用和括号的顺序等。
例如,再次在 C# 中:
10f / float.Epsilon / float.MaxValue
也
(10f / float.Epsilon) / float.MaxValue
给出 20971522.0f。
然而,数学上等价的表达式:
10f / (float.Epsilon / float.MaxValue)
给出无穷大。
于 2012-01-13T17:11:44.557 回答