#include <stdio.h>
#include <stdint.h>
#include <fenv.h>
#include <math.h>

int main()
{
    typedef union { uint32_t u; float f; } ufloat;
    ufloat val;
    float arg = 2401.999999;
    int r;
    r = fesetround(FE_DOWNWARD);
    val.f = sqrtf(arg);
    printf ("FE_DOWNWARD   %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_TONEAREST);
    val.f = sqrtf(arg);
    printf ("FE_TONEAREST  %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_TOWARDZERO);
    val.f = sqrtf(arg);
    printf ("FE_TOWARDZERO %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_UPWARD);
    val.f = sqrtf(arg);
    printf ("FE_UPWARD     %22.13a [0x%x] %d\n", val.f, val.u, r);
    return 0;
}
主机:Win10 x64。
结果:
情况1。
$ clang t2.c -o t2.clang.exe && ./t2.clang.exe
FE_DOWNWARD 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TONEAREST 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TOWARDZERO 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_UPWARD 0x1.8814e60000000p + 5 [0x42440a73] 0

$ clang --version
clang版本8.0.1(标签/RELEASE_801/final)

情况2
$ gcc t2.c -o t2.gcc.exe && ./t2.gcc.exe
FE_DOWNWARD 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TONEAREST 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TOWARDZERO 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_UPWARD 0x1.8814e60000000p + 5 [0x42440a73] 0

$ gcc-版本
海湾合作委员会(GCC)10.2.0

情况3。
cl t2.c && t2
适用于x64的Microsoft(R)C/C++优化编译器版本19.25.28611
...
FE_DOWNWARD 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_TONEAREST 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TOWARDZERO 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_UPWARD 0x1.8814e60000000p + 5 [0x42440a73] 0

情况4
cl t2.c && t2
适用于x86的Microsoft(R)C/C++优化编译器版本19.25.28611
...
系统无法执行指定的程序。
出现弹出窗口:“病毒和线程保护:Windows Defender Antivirus发现威胁。获取详细信息。”

情况5
wandbox.org:gcc HEAD 11.0.0 20200
$ gcc prog.c -Wall -Wextra -std = c99“-lm”
FE_DOWNWARD 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_TONEAREST 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TOWARDZERO 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_UPWARD 0x1.8814e60000000p + 5 [0x42440a73] 0

案例6
wandbox.org:c HEAD 12.0.0
$ clang prog.c -Wall -Wextra -std = gnu11“-lm”
FE_DOWNWARD 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_TONEAREST 0x1.8814e60000000p + 5 [0x42440a73] 0
FE_TOWARDZERO 0x1.8814e40000000p + 5 [0x42440a72] 0
FE_UPWARD 0x1.8814e60000000p + 5 [0x42440a73] 0

问题:
  • 为什么编译器之间会有不同的结果(0x42440a720x42440a73)?
  • 如何在编译器之间获得相同的结果?
  • 最佳答案


    至少对于较旧的gcc,不需要<fenv.h>支持。
    参见floating-point environment access in <fenv.h>, Library feature, no compiler support required.
    当我使用“GNU C11(GCC)版本9.3.0(x86_64-pc-cygwin)”进行编译时,以下内容

    #include <fenv.h>
    #pragma STDC FENV_ACCESS ON
    
    我收到以下信息:
    warning: ignoring #pragma STDC FENV_ACCESS [-Wunknown-pragmas]
    
    另请参见If pragma STDC FENV_ACCESS is absent, does it mean default rounding mode?pragma STDC FENV_ACCESS ON is not supported

    没有帮助,但不要使用fenv.h的可选功能或避免选择编译器。
    可能存在一个gcc编译时标志来提供帮助,但是我不知道一个。
    还可以使用#pragma STDC FENV_ACCESS ON @Eric Postpischil。这可能不会解决此问题,但会阻止相关问题。

    关于c - IEEE 754 : sqrtf() with fesetround(): different results between compilers: 0x42440a72 vs. 0x42440a73,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63870900/

    10-11 12:19