linux - GCC处理不同优化级别的浮点数比较

我有一些比较两个浮点值的简单代码来说明我在gcc优化中看到的一个问题,并希望有人能帮助我找出在某些可重复的情况下,它产生的输出是不同的。
首先,我知道比较float值和==是不好的,因为在尾数中可以有很小的偏差,但是在我的例子中不是这样的。我的问题是基于2个因素的输出变化。1)如果我取消了STD::CUT线,优化标志I通过,而2)。
为什么gcc生成的代码在-o2下运行不同?
如果取消对打印的注释,为什么在-o2下编译的代码可以工作?
这是我正在测试的代码:

#include <iostream>

const float ft_to_m          =  (float)0.3048; 
const float m_to_ft          =  (float)3.28083989501;


float FeetToKilometers( float & Feet ) {
  float Kilometers;
  Kilometers = (ft_to_m * Feet) / 1000.;
  return Kilometers;
}

int main(void)
{
    float feet = 20000.;
    float old_val = 0;
    float new_val = FeetToKilometers(feet );
    float diff_val = 0;

    int *old_int = reinterpret_cast<int*>(&old_val);
    int *new_int = reinterpret_cast<int*>(&new_val);

    for (int i=0; i<2; i++)
    {

    new_val = FeetToKilometers(feet );
    diff_val = old_val-new_val;

    //std::cout << "Random COUT that makes this work" << std::endl;

        if(old_val==new_val)
    {
             std::cout << "old_val==new_val" << std::endl;
         std::cout << std::hex << *old_int << "," << std::hex << *new_int << std::endl;
             std::cout << "diff_val = " << diff_val <<std::endl;
    }
        else
        {
            std::cout << "old_val!=new_val" <<std::endl;
        std::cout << std::hex << *old_int << "," << std::hex << *new_int << std::endl;
            std::cout << "diff_val = " << diff_val <<std::endl;
            old_val=FeetToKilometers(feet);
        }
    }

    return 0;
}

在Linux/cygwin上使用-o0、-o1和-o3(g++o test.cpp)编译时,我得到以下输出:
美元/a.exe
老瓦尔!=新值
0.40C3126F
差异值=-6.096
旧值==新值
40C3126F、40C3126F
差异值=0
这个输出是正确的,您可以看到浮点数的位(新值和旧值)是相同的。当我使用-o2标志(g++-o2 test.cpp)编译时,我得到以下信息:
美元/a.exe
老瓦尔!=新值
0.40C3126F
差异值=-6.096
老瓦尔!=新值
40C3126F、40C3126F
差值=1.19209E-07
我认为这个输出是错误的。即使这两个值的位是相同的,减去它们,==检查表明它们是不同的。如果我取消评论STD::CUT线,用-O2标志(G++-O2 Test.CPP)重建,我得到以下内容:
美元/a.exe
使这项工作发挥作用的随机能力
老瓦尔!=新值
0.40C3126F
差异值=-6.096
使这项工作发挥作用的随机能力
旧值==新值
40C3126F、40C3126F
差值=1.19209E-07
这在旧的_val==new_val中是正确的,即使减法仍然显示出细微的差别。
如果英尺为2000英尺,则此代码也适用于-o2,而不是20000英尺。
有人能解释为什么编译后的代码是这样的行为吗?我想知道为什么2位相同的浮点值不能与==进行比较。
GCC版本3.4.4

最佳答案

优化级别和周围的代码可能会影响diff_val计算中使用的值是从内存还是从寄存器中提取的。处理器
在一种情况下,可以使用80位内部浮点寄存器和32位浮点寄存器
在另一种情况下,来自内存的点值会产生意外的结果。
还有另一个避免使用==进行浮点比较的原因!

本文翻译自 https://stackoverflow.com/questions/3765200/

网站遵循 CC BY-SA 4.0 协议,转载或引用请注明出处。

标签 linux gcc floating-point equals mantissa


相关文章:

linux - Linux中的调度:在计算机空闲时运行任务(=无用户输入)

c - GCC(NOLOAD)指令导致错误的内存映射

ruby - Ruby中的浮点整数

python - 我使用整数还是浮点数?

c++ - 强制程序以root身份启动并稍后将其删除

java - AWT和Oracle Secure Global Desktop

linux - Linux Bash输入

c - GCC和CLang无法识别Unicode字符串

c - 如何使用gcc 4.8.4消除C中未使用的参数警告[-Wunused-parameter] [重复]

c - 浮法双倍?计算错误,使用double [关闭]