我有一个可能是零的数字。我除以那个数字,所以我想测试它是否为零以防止NaN和无穷大。由于分区内的舍入错误,我是否仍然可以创建NaNs /无穷大?
double x; // might be zero
double y;
if(x != 0) return y / x;
修改
感谢您的回复。我接下来会添加一些子参数。
1)假设x和y都不是NaN / + inf或-inf,导致-inf / + inf的除法会导致更多CPU周期或任何其他不需要的行为吗? (会崩溃吗?)
2)有没有办法防止分裂导致无穷大?使用偏移等。
答案 0 :(得分:9)
非零除法仍可创建纳米/无穷大
是
如果遵循IEEE-754则:
其他陈述的规则可能有所不同。
2)有没有办法防止分裂导致无穷大
这应该在很大程度上防止:
#include <cfenv>
#include <cassert>
#include <cmath>
#include <limits>
// ...
static_assert(std::numeric_limits<decltype(x)>::is_iec559, "Unknown floating point standard.");
#pragma STDC FENV_ACCESS ON
int failed = std::fesetround(FE_TOWARDZERO);
assert(!failed);
if(x != 0 && std::isfinite(x) && std::isfinite(y))
return y / x;
else
throw std::invalid_argument("informative message");
某些编译器可能需要非默认选项才能启用完全符合IEEE 754标准(GCC上为-frounding-math
)。
答案 1 :(得分:6)
将一个非常小的数字除以一个非常大的数字,或两个非常大的数字的乘法,可能会产生一个无穷大的数字&#34;。将无穷大除以另一个无穷大将产生NaN。例如,(1E300/1E-300)/(1E300/1E-300)
或(1E300*1E300)/(1E300*1E300)
都会产生NaN。
答案 2 :(得分:5)
是的,请看下面的代码
#include <iostream>
int main ()
{
double x = 1, y = 2;
while (y != 0) {
std::cout << y << " " << x / y << std::endl;
y /= 2;
}
}
在某个时刻你会得到:
8.9003e-308 1.12356e+307
4.45015e-308 2.24712e+307
2.22507e-308 4.49423e+307
1.11254e-308 8.98847e+307
5.56268e-309 inf
2.78134e-309 inf
1.39067e-309 inf
6.95336e-310 inf