如果我想检查正浮点数A是否小于另一个正浮点数B的倒数平方(在C99中),如果B非常小,可能会出错吗?
我可以想象将其视为
if(A<1/(B*B))
但如果B足够小,这可能会导致无穷大吗?如果发生这种情况,代码是否仍能在所有情况下正常工作?
以类似的方式,我可能会这样做
if(1/A>B*B)
...这可能会稍微好些,因为如果B很小,B * B可能为零(这是真的吗?)
最后,我无法想象的解决方案是
if(sqrt(1/A)>B)
我认为不会导致零分割,但如果A接近于零,仍然可能会出现问题。
基本上,我的问题是:
if(B*A*B<1)
我是按照这个顺序做的,因为它在视觉上是明确的,首先发生乘法。
答案 0 :(得分:7)
如果你想处理A
和B
的所有可能值,那么你需要有点小心,但这确实不太复杂。
使用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
并且你的问题不是问题平台遵循合理的数字模型。)
因为你知道先验 a
和b
都是正数,所以a*b*b
无法生成NaN,所以你需要不要担心这种情况。溢出和下溢是唯一可能的错误行为,我们已经考虑过它们。如果您需要支持a
或b
可能为零或无穷大的情况,那么您需要更加小心。
回答您的直接问题:(答案假定为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)
答案 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
是正确答案的原因。