由于减法中的浮点错误,在以下情况下是否可能除以零?
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;
由于减法中的浮点错误,在以下情况下是否可能除以零?
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;
假设 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,但该定理对于大多数“合理的”浮点系统都是正确的。
这将阻止您完全除以零,但这并不意味着仍然不会因此而结束+/-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
。
两个代码片段 () 之间没有区别 - 事实上,优化器甚至可以将两个片段优化为相同的二进制代码,假设没有进一步使用该divisor
变量。
但是请注意,除以浮点零0.0
不会导致运行时错误,而是会产生inf
or -inf
。