【发布时间】:2020-12-31 09:13:18
【问题描述】:
#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 (tags/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 Microsoft (R) C/C++ 优化编译器版本 19.25.28611 for x64 ... 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 Microsoft (R) C/C++ 优化编译器版本 19.25.28611 for x86 ... 系统无法执行指定的程序。 出现弹出窗口:“病毒和线程保护: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: 铿锵头 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问题:
- 为什么编译器之间的结果不同(
0x42440a72与0x42440a73)? - 如何在编译器之间获得相同的结果?
【问题讨论】:
-
您可以 - 并且必须发布这些 - 只是不要将 所有内容都作为代码块。将单独运行的标题格式化为普通文本!
-
@AnttiHaapala,感谢您的提示(使用
<pre>code</pre>模式)! -
某些编译器和库不太支持更改浮点舍入模式,但源代码中的一个问题是,如果您使用
FENV_ACCESS更改舍入模式,C 标准没有定义行为关闭(C 2018 7.6.1 2)。您可以在支持它的编译器中使用#pragma STDC FENV_ACCESS ON将其打开。 -
我是否理解正确,在
FENV_ACCESS关闭的情况下,由于UB,我们不能依赖fesetround()返回值?在上面的示例中,fesetround()确实 [错误地] 返回了0(即成功设置了舍入方向),但从结果中我们看到未设置舍入方向。
标签: c floating-point rounding ieee-754 cl