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

ruh*_*ner 9 c++ nan division infinity

我有一个可能是零的数字.我除以那个数字,所以我想测试它是否为零以防止NaN和无穷大.由于分区内的舍入错误,我是否仍然可以创建NaNs /无穷大?

double x; // might be zero
double y;

if(x != 0) return y / x;
Run Code Online (Sandbox Code Playgroud)

编辑

谢谢你的回复.我会添加一些子问题.

1)假设x和y都不是NaN/+ INF或-INF,会导致-INF/+ INF导致更多的CPU周期或任何其他不希望的行为的分割?(会崩溃吗?)

2)有没有办法防止分裂导致无穷大?使用偏移等.

eer*_*ika 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");
Run Code Online (Sandbox Code Playgroud)

某些编译器可能需要非默认选项才能启用完全符合IEEE 754(-frounding-math在GCC上).


sup*_*cat 6

将非常小的数字除以非常大的数字,或者将两个非常大的数字相乘,可能会产生"无穷大".将无穷大除以另一个无穷大将产生NaN.例如,(1E300/1E-300)/(1E300/1E-300)(1E300*1E300)/(1E300*1E300)两者都会产生NaN.


vad*_*bot 5

是的,请看下面的代码

#include <iostream>
int main ()
{
    double x = 1, y = 2;
    while (y != 0) {
        std::cout << y << " " << x / y << std::endl;
        y /= 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

在某个时刻你会得到:

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
Run Code Online (Sandbox Code Playgroud)