C: 无序浮点比较不引发 FE_INVALID
C: unordered floating-point comparison does not raise FE_INVALID
我 运行 遇到了浮点数比较的问题。使用 <
运算符将值与 NaN 进行比较时,我希望设置 FE_INVALID
标志。 <
运算符应根据 C11 标准(以及 IEEE-754)升起标志:
The isless
macro determines whether its first argument is less than
its second argument. The value of isless(x, y)
is always equal to
(x) < (y)
; however, unlike (x) < (y)
, isless(x, y)
does not
raise the "invalid" floating-point exception when x
and y
are
unordered.
这是重现我的问题的示例程序:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main()
{
volatile float a = 12.0f;
volatile float b = NAN;
volatile int c;
feclearexcept(FE_ALL_EXCEPT);
c = (a < b);
if (fetestexcept(FE_INVALID))
printf("FE_INVALID\n");
else
printf("Not invalid\n");
return 0;
}
在我的机器上(Linux,march=broadwell
)它 returns "Not invalid"。
我使用 GCC v7.2.0 编译它,使用 -std=c11
选项(不使用它不会改变结果中的任何内容)。发出的 x86 指令是 UCOMISS
,它只会引发 NaN 信号异常——我希望看到 COMISS
,因为这会在所有 NaN 比较中引发异常,因为 NaN 是无序的,无论它们是否是是否发出信号。
我是不是在我的代码中犯了错误或者忘记了一些编译器选项来使行为符合 IEEE?忽略此处引发异常的需要可能是编译器中的错误(或性能优化)?
好的,所以我冒险获得了最新的 GCC 版本 (8.2) 运行。
代码在 GCC 8.2.0 下编译时的行为符合预期,因此我假设问题是编译器错误。我没有尝试 7.2.0 和 8.2 之间的其他版本来查看它从什么时候开始工作,但使用 8.2 对我来说已经足够了。
我 运行 遇到了浮点数比较的问题。使用 <
运算符将值与 NaN 进行比较时,我希望设置 FE_INVALID
标志。 <
运算符应根据 C11 标准(以及 IEEE-754)升起标志:
The
isless
macro determines whether its first argument is less than its second argument. The value ofisless(x, y)
is always equal to(x) < (y)
; however, unlike(x) < (y)
,isless(x, y)
does not raise the "invalid" floating-point exception whenx
andy
are unordered.
这是重现我的问题的示例程序:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main()
{
volatile float a = 12.0f;
volatile float b = NAN;
volatile int c;
feclearexcept(FE_ALL_EXCEPT);
c = (a < b);
if (fetestexcept(FE_INVALID))
printf("FE_INVALID\n");
else
printf("Not invalid\n");
return 0;
}
在我的机器上(Linux,march=broadwell
)它 returns "Not invalid"。
我使用 GCC v7.2.0 编译它,使用 -std=c11
选项(不使用它不会改变结果中的任何内容)。发出的 x86 指令是 UCOMISS
,它只会引发 NaN 信号异常——我希望看到 COMISS
,因为这会在所有 NaN 比较中引发异常,因为 NaN 是无序的,无论它们是否是是否发出信号。
我是不是在我的代码中犯了错误或者忘记了一些编译器选项来使行为符合 IEEE?忽略此处引发异常的需要可能是编译器中的错误(或性能优化)?
好的,所以我冒险获得了最新的 GCC 版本 (8.2) 运行。
代码在 GCC 8.2.0 下编译时的行为符合预期,因此我假设问题是编译器错误。我没有尝试 7.2.0 和 8.2 之间的其他版本来查看它从什么时候开始工作,但使用 8.2 对我来说已经足够了。