可以通过非零划分仍然创建纳/无穷大

时间:2016-07-25 15:30:31

标签: c++ nan division infinity

我有一个可能是零的数字。我除以那个数字,所以我想测试它是否为零以防止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)有没有办法防止分裂导致无穷大?使用偏移等。

3 个答案:

答案 0 :(得分:9)

  

非零除法仍可创建纳米/无穷大

如果遵循IEEE-754则:

  • 如果任一操作数为NaN,则结果为NaN。
  • 如果分子和分子都是无穷大,则结果为NaN。
  • 如果只有分子是无穷大,则结果为无穷大。
  • 如果按小分子(或大分子)除法溢出,结果可能是无穷大,具体取决于当前的舍入模式。

其他陈述的规则可能有所不同。

  

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