无穷大的变量不等于无穷大

Lia*_*aVa 0 c++ gcc

我遇到了一个错误,我的无穷大变量不等于无穷大。我什至不确定在哪种情况下。

这是最小的例子:

#include <iostream>
#include <limits>
#include <cmath>

using namespace std;


constexpr auto NT_INF = std::numeric_limits<double>::infinity();


// prints a number byte-by-byte
void printN(double n){
    auto tmp = (uint8_t*)&n;
    for (int i = 0; i < 8; i++) {
        wprintf(L"%4d ", tmp[i]);
    }
    wprintf(L"\n");
};


double * genNumbers() {
    double * numbers = new double[6];
    
    numbers[0] = 100;
    numbers[1] = 1;
    numbers[2] = 198263783302;
    numbers[3] = 198263783302;
    numbers[4] = 100;
    numbers[5] = 0;
    
    return numbers;
}


int main()
{
    // leave no chance for the compiler to optimize variables away
    double * numbers = genNumbers();
    
    // floor((100. * 1.) / (198263783302. - 198263783302.)) / 100.;
    numbers[5] = floor((numbers[0] * numbers[1]) / (numbers[2] - numbers[3])) / numbers[4];
    double number = numbers[5];

    printN(number);
    printN(NT_INF);
    
    wprintf(L"%f, %f, %d, %d, %d, %d\n", number, NT_INF, number == 1.0 / 0.0, number == NT_INF, isinf(NT_INF), isinf(number));
    
    delete numbers;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的 GCC 编译器标志是: -fno-reorder-blocks -ffast-math -march=native -fno-exceptions -Ofast -fmodulo-sched -fgcse-sm -fgcse-las -fno-inline-small-functions -flto=2 -fgcse-lm -fira-region=all

如果你尝试在 onlinegdb 中运行它,那么你会得到类似的结果

   0    0    0    0    0    0  240  127 
   0    0    0    0    0    0  240  127 
inf, inf, 1, 1, 1, 0
Run Code Online (Sandbox Code Playgroud)

从输出来看,和NT_INFnumber相同的printN。同时,isinfnumber不是无穷大...但 printf 说它是???

如果我尝试在本地编译,情况会更糟(我想,这是由于-march=native)。

   0    0    0    0    0    0  240  127 
   0    0    0    0    0    0  240  127 
inf, inf, 0, 0, 1, 0
Run Code Online (Sandbox Code Playgroud)

所以这里number变量甚至不等于无穷大,使用简单的==

我完全不知道这个例子(我的真实代码)有什么问题。也许是由于某些标志或它们的组合,但有太多的组合无法尝试。

use*_*522 6

-ffast-math暗示-ffinite-math-only,这意味着编译器可以在浮点值始终有限(即永远不会无穷大或 NaN)的假设下进行优化。您违反了该假设,因此您的代码具有实际的未定义行为。

请参阅海湾合作委员会文档

-Ofast顺便说-ffast-math一句,我认为其他几个选项也是多余的。而且,这些选择对我来说似乎很奇怪。一切似乎都在尝试最大性能,但随后您就-fno-reorder-blocks禁用-fno-inline-small-functions了基本优化。

多个编译器选项会导致编译器的行为不符合 C、C++ 和 IEEE 754 标准。如果您不完全理解这些优化选项的作用以及对标准分歧的暗示,则不应使用此类优化选项。