当划分1 /一个非常小的浮子时会发生坏事吗?

时间:2010-06-02 02:05:55

标签: c floating-point division divide-by-zero

如果我想检查正浮点数A是否小于另一个正浮点数B的倒数平方(在C99中),如果B非常小,可能会出错吗?

我可以想象将其视为

if(A<1/(B*B))

但如果B足够小,这可能会导致无穷大吗?如果发生这种情况,代码是否仍能在所有情况下正常工作?

以类似的方式,我可能会这样做

if(1/A>B*B)

...这可能会稍微好些,因为如果B很小,B * B可能为零(这是真的吗?)

最后,我无法想象的解决方案是

if(sqrt(1/A)>B)

我认为不会导致零分割,但如果A接近于零,仍然可能会出现问题。

基本上,我的问题是:

  • 如果X大于零(但很小),1 / X是否可以无穷大?
  • 如果X大于零,X * X能否为零?
  • 与无限的比较会按照我期望的方式进行吗?
编辑:对于那些想知道的人,我最终做了

if(B*A*B<1) 

我是按照这个顺序做的,因为它在视觉上是明确的,首先发生乘法。

4 个答案:

答案 0 :(得分:7)

如果你想处理AB的所有可能值,那么你需要有点小心,但这确实不太复杂。

使用a*b*b < 1.的建议很好;如果b非常小,a*b*b下溢为零,那么a必然小于1./(b*b)。相反,如果b太大而a*b*b溢出到无穷大,那么条件将(正确地)不满足。 ( Potatoswatter 正确地在另一篇帖子的评论中指出,如果您编写b*b*a 可能会正常工作,因为b*b可能会溢出到如果条件应该为真,则无穷大,如果a恰好是非正规的。但是,在C中,乘法从左到右关联,因此如果你写a*b*b并且你的问题不是问题平台遵循合理的数字模型。)

因为你知道先验 ab都是正数,所以a*b*b无法生成NaN,所以你需要不要担心这种情况。溢出和下溢是唯一可能的错误行为,我们已经考虑过它们。如果您需要支持ab可能为零或无穷大的情况,那么您需要更加小心。

回答您的直接问题:(答案假定为IEEE-754算术)

  

如果X大于零(但很小),1 / X是否可以无穷大?

是的!如果x是一个小的正非正规值,则1/x会溢出并产生无穷大。例如,在默认舍入模式下的双精度中,1 / 0x1.0p-1024将溢出。

  

如果X大于零,X * X是否可以为零?

是的!在默认舍入模式下的双精度中,x的所有小于0x1.0p-538的值(C99十六进制格式中的2**-578)左右都具有此属性。

  

与无限的比较会按照我期望的方式进行吗?

是的!这是IEEE-754的最佳功能之一。

答案 1 :(得分:5)

好的,重新发布作为答案。

尝试使用像if ( A*B*B < 1. )这样的算术等效比较。你可能会遇到很大的数字。

仔细查看角落案件的IEEE 754

答案 2 :(得分:3)

你想避免分裂,所以诀窍是修改方程式。您可以将第一个等式的两边乘以(b * b)得到:

b*b*a < 1.0

这不会有任何分歧所以应该没问题。

答案 3 :(得分:1)

分区本身并不是那么糟糕。但是,由于非规范化数字,标准IEEE 754 FP类型允许指数的负负范围大于正数。例如,float的范围从1.4×10 -45 到3.4×10 -38 ,因此您不能采用2×10 的倒数 - 44

因此,正如杰里米所说,首先将A乘以B,其中一个具有正指数而另一个具有负指数,以避免溢出。

这就是A*B*B<1是正确答案的原因。