浮点运算在g ++和clang ++之间有所不同吗?

138*_*138 1 c++ g++ clang ieee-754

我遇到了一个似乎与平台相关的错误.我得到了clang ++和g ++的不同结果,但仅限于我的32-Debian Machine.我一直认为IEEE 754是标准化的,所有遵守标准的编译器都会有相同的行为.如果我错了,请告诉我,我对此非常困惑.另外,我意识到依赖浮点比较通常不是一个好主意.

#define DEBUG(line) std::cout <<"\t\t" << #line << " => " << line << "\n";
#include <iostream>
int main() {
    double x = 128.0, y = 255.0;
    std::cout << "\n";
    DEBUG(  x/y)
    DEBUG(  ((x/y) == 128.0/255.0)) 
    DEBUG(  (128.0/255.0)   )
    DEBUG(  ((x/y)-(x/y)))
    DEBUG(  ((x/y)-(128.0/255.0))   )  
    DEBUG(  ((128.0/255.0)-0.501961) ) 
    std::cout << "\n";  
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是我的输出

[~/Desktop/tests]$ g++ float_compare.cc -o fc
[~/Desktop/tests]$./fc

        x/y => 0.501961
        ((x/y) == 128.0/255.0) => 0
        (128.0/255.0) => 0.501961
        ((x/y)-(x/y)) => 0
        ((x/y)-(128.0/255.0)) => 6.9931e-18
        ((128.0/255.0)-0.501961) => -2.15686e-07

[~/Desktop/tests]$clang++ float_compare.cc -o fc
[~/Desktop/tests]$./fc

        x/y => 0.501961
        ((x/y) == 128.0/255.0) => 1
        (128.0/255.0) => 0.501961
        ((x/y)-(x/y)) => 0
        ((x/y)-(128.0/255.0)) => 0
        ((128.0/255.0)-0.501961) => -2.15686e-07
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 5

标准允许中间结果使用扩展精度,即使在完全合规模式下(许多编译器默认情况下也没有).它说[basic.fundamental]:

本国际标准对浮点运算的准确性没有要求

有关比较g ++和clang的特殊情况,请参阅https://gcc.gnu.org/wiki/FloatingPointMath

没有任何明确的选择,GCC假定舍入到最近或甚至并且不关心信号NaN.

对于没有SSE2支持的传统x86处理器,对于m68080处理器,GCC只能完全符合IEEE双扩展(long double)类型的IEEE 754语义.使用双扩展精度执行IEEE双精度和IEEE单精度值的操作.为了正确舍入这些操作,GCC必须保存FPU控制和状态字,启用舍入到24或53个尾数位,然后恢复FPU状态.这太昂贵了.

由于SSE(64位)和x87(80位)之间的扩展精度不同,编译时计算的结果可能不仅取决于编译器及其版本,还取决于构建编译器的标志.

您知道IEEE 754规则未生效的方式是通过检查numeric_limits<T>::is_iec559.