划分下溢

时间:2012-01-13 16:58:07

标签: computer-science divide-by-zero underflow

为什么除数下限仅在除数远小于被除数时产生,如果分母接近零而不管股息的大小如何,它是否应该发生?

1 个答案:

答案 0 :(得分:3)

来自http://www.strw.leidenuniv.nl/docs/intel/f_ug/ieee_ovw.htm

  

如果舍入结果具有指数,则会发生下溢异常   这太小了,无法使用浮点格式表示   结果。

这意味着当被除数和除数的比率小到足以超过浮点格式的精度时,就会发生错误,而不是对诸如epsilon之类的特定值的任何依赖。

当分母接近零时,假设分子为非零,分裂的结果将接近无穷大。当分子接近零时,假设非零分母,结果接近零。当这个值足够小时,就会出现这种情况。

如果分子和分母的值非常接近,即使它们非常小,也可以获得有用的结果,因此非常小的分子不一定会导致下溢。

示例

在C#中,epsilon是1.401298E-45。

epsilon / epsilon == 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.

是否获得下溢或除零可能取决于编译器,您的使用和parenthisis的顺序等。

例如,再次在C#中:

10f / float.Epsilon / float.MaxValue

以及

(10f / float.Epsilon) / float.MaxValue

给出20971522.0f。

然而,数学上的等式表达式:

10f / (float.Epsilon / float.MaxValue)

给出无限。