gcc 具有无穷大的变量不等于无穷大

vxf3dgd4  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(309)

我遇到了一个错误,我的变量与无穷大不等于无穷大。我都不确定是哪种情况。
下面是最小的例子:

#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;
}

我的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

所以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

因此,这里的number变量甚至不等于无穷大,使用简单的==
我完全不知道这个例子(我的真实的代码)有什么问题。也许这是由于一些旗帜或他们的组合,但有太多的组合,以尝试他们。

enyaitl3

enyaitl31#

-ffast-math意味着-ffinite-math-only,这意味着编译器可以在浮点值总是有限的假设下进行优化(即永远不是无穷大或NaN)。你违反了这个假设,所以你的代码有实际的未定义行为。
参见GCC documentation
-Ofast也意味着-ffast-math,我认为其他几个选项是多余的。而且,这些选择对我来说很奇怪。一切似乎都在尝试最大化性能,但您有-fno-reorder-blocks-fno-inline-small-functions,它们禁用了基本优化。
您的几个编译器选项会导致编译器的行为不符合C、C++和IEEE 754标准。如果您不完全理解这些优化选项对标准散度的作用和含义,则不应使用它们。

相关问题