7

由于减法中的浮点错误,在以下情况下是否可能除以零?

float x, y, z;
...
if (y != 1.0)
    z = x / (y - 1.0);

换句话说,以下是否更安全?

float divisor = y - 1.0;
if (divisor != 0.0)
    z = x / divisor;
4

3 回答 3

6

假设 IEEE-754 浮点,它们是等价的。

这是 FP 算术的基本定理,对于有限的 x 和 y,x - y == 0 当且仅当 x == y,假设逐渐下溢。

如果低于正常的结果被刷新为零(而不是逐渐下溢),则该定理仅在结果 x - y 正常时才成立。因为 1.0 被很好地缩放,y - 1.0绝不是次正规的,所以y - 1.0当且仅当 y 正好是 1.0 时为零,无论如何处理下溢。

当然,C++ 不保证 IEEE-754,但该定理对于大多数“合理的”浮点系统都是正确的。

于 2012-10-10T19:04:49.433 回答
5

这将阻止您完全除以零,但这并不意味着仍然不会因此而结束+/-inf。分母可能仍然足够小,以至于答案不能用 a 表示double,你最终会得到 a inf。例如:

#include <iostream>
#include <limits>

int main(int argc, char const *argv[])
{
    double small = std::numeric_limits<double>::epsilon();
    double large = std::numeric_limits<double>::max() / small;
    std::cout << "small: " << small << std::endl;
    std::cout << "large: " << large << std::endl;
    return 0;
}

在这个程序small中 是非零的,但它是如此之小以至于large超出了double和的范围inf

于 2012-10-10T18:15:31.107 回答
2

两个代码片段 () 之间没有区别 - 事实上,优化器甚至可以将两个片段优化为相同的二进制代码,假设没有进一步使用该divisor变量。

但是请注意,除以浮点零0.0不会导致运行时错误,而是会产生infor -inf

于 2012-10-10T18:04:11.490 回答