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

Jer*_*wen 7 c floating-point division divide-by-zero

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

我可以想象检查它

if(A<1/(B*B))
Run Code Online (Sandbox Code Playgroud)

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

我也许会这样做

if(1/A>B*B)
Run Code Online (Sandbox Code Playgroud)

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

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

if(sqrt(1/A)>B)
Run Code Online (Sandbox Code Playgroud)

我认为这不会导致零分割,但如果A接近于零,仍可能存在问题.

所以基本上,我的问题是:

  • 如果X大于零(但很小),1/X是否可以无穷大?
  • 如果X大于零,X*X能否为零?
  • 与无限的比较会按照我期望的方式进行吗?

编辑:对于那些想知道的人,我最终做了

if(B*A*B<1) 
Run Code Online (Sandbox Code Playgroud)

我按顺序做了,因为它在视觉上是明确的,首先发生乘法.

Ste*_*non 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(2**-578C99十六进制格式)的值都具有此属性.

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

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


Nik*_*sov 5

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

尝试使用算术上等效的比较if ( A*B*B < 1. ).但是你可能会遇到很大的问题.

仔细查看IEEE 754的角落情况.

  • 实际上,只要他不需要支持零或无穷大作为"a"或"b"的值(听起来他没有),那么就没有角落问题; 他们都正确地掉了. (3认同)