7

如果我想检查正浮点 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

4 回答 4

7

如果你想处理 and 的所有可能值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并且您的平台遵循合理的数字模型,这不是问题。)

因为您先验地知道a并且b都是正数,所以无法a*b*b生成 NaN,因此您不必担心这种情况。上溢和下溢是唯一可能的不当行为,我们已经对它们进行了解释。如果您需要支持aorb可能为零或无穷大的情况,那么您需要更加小心。

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

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

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

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

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

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

是的!这是 IEEE-754 的最佳特性之一。

于 2010-06-02T03:10:33.303 回答
5

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

尝试使用算术等价比较,例如if ( A*B*B < 1. ). 但是,您可能会遇到非常大的数字的麻烦。

仔细查看IEEE 754以了解您的极端情况。

于 2010-06-02T02:39:59.970 回答
3

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

b*b*a < 1.0

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

于 2010-06-02T02:33:44.673 回答
1

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

因此,正如 Jeremy 建议的那样,首先将 A 乘以 B,其中一个具有正指数,另一个具有负指数,以避免溢出。

这就是为什么A*B*B<1是正确的答案。

于 2010-06-02T03:13:59.930 回答