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

标签 c++ g++ clang ieee-754

我遇到了一个似乎与平台相关的错误。对于 clang++ 和 g++,我得到了不同的结果,但仅在我的 32-Debian 机器上。我一直认为 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;
}

这是我的输出

[~/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

最佳答案

该标准允许中间结果使用扩展精度,即使在完全合规模式下也是如此(许多编译器默认情况下并不处于这种模式)。它在 [basic.fundamental] 中说:

This International Standard imposes no requirements on the accuracy of floating-point operations

对于比较 g++ 和 clang 的特定情况,请参阅 https://gcc.gnu.org/wiki/FloatingPointMath

Without any explicit options, GCC assumes round to nearest or even and does not care about signalling NaNs.

还有

For legacy x86 processors without SSE2 support, and for m68080 processors, GCC is only able to fully comply with IEEE 754 semantics for the IEEE double extended (long double) type. Operations on IEEE double precision and IEEE single precision values are performed using double extended precision. In order to have these operations rounded correctly, GCC would have to save the FPU control and status words, enable rounding to 24 or 53 mantissa bits and then restore the FPU state. This would be far too expensive.

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

您知道 IEEE 754 规则无效的方法是检查 numeric_limits<T>::is_iec559 .

关于c++ - g++ 和 clang++ 之间的浮点运算有所不同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49471943/

相关文章:

c++ - 从可执行文件中找出编译优化标志

ruby - sudo gem install jekyll -- 失败 -- clang 错误未知参数

c++ - Armadillo 中的字段初始化

c++ - 用 if 语句分配引用?

c++ - 如何在C++中获取数学表达式作为输入

c++ - 尽管在参数中提供了所有需要的库,但为什么编译器会抛出 "undefined reference to ..."

c++ - 没有功能包的 VS 2008 的简单 C++ 正则表达式库

c++ - 在我的 C++ 程序中,所有线程都停留在 "select () from/lib64/libc.so.6",内存使用率很高

将指针转换为 _Atomic 指针和 _Atomic 大小

c++ - 修改嵌套lambda中捕获的参数 : gcc vs clang?