由于减法中的浮点误差,在以下情况下是否可以除零?
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;
答案 0 :(得分:6)
假设IEEE-754浮点数,它们是等价的。
这是FP算法的基本定理,对于有限x和y,x - y == 0当且仅当x == y时,假设逐渐下溢。
如果将次正规结果刷新为零(而不是逐渐下溢),则该定理仅在结果x-y正常时才成立。因为1.0被很好地缩放,所以y - 1.0
永远不会是正常的,所以y - 1.0
当且仅当y恰好是1.0时才为零,无论如何处理下溢。
答案 1 :(得分:5)
这样可以防止您正好除以零,但这并不意味着结果仍然不会以+/-inf
结束。分母可能仍然足够小,因此double
无法表示答案,最终会得到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
的范围且为{{1}}。
答案 2 :(得分:2)
两个代码片段之间没有区别() - 事实上,优化器甚至可以将两个片段优化为相同的二进制代码,假设没有进一步使用divisor
变量。
但请注意,按浮点零0.0
除法不会导致运行时错误,但会生成inf
或-inf
。