C:无序浮点比较不会引发 FE_INVALID

Posted

技术标签:

【中文标题】C:无序浮点比较不会引发 FE_INVALID【英文标题】:C: unordered floating-point comparison does not raise FE_INVALID 【发布时间】:2019-02-07 11:09:13 【问题描述】:

我遇到了浮点比较的问题。当使用 < 运算符将值与 NaN 进行比较时,我希望设置 FE_INVALID 标志。 < 运算符应根据 C11 标准(也根据 IEEE-754)升旗:

isless 宏判断它的第一个参数是否小于 它的第二个论点。 isless(x, y) 的值始终等于 (x) < (y);然而,不同于(x) < (y)isless(x, y) 不 当xy引发“无效”浮点异常 无序

这是一个重现我的问题的示例程序:

#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)上,它返回“Not invalid”。 我使用 GCC v7.2.0 编译它,使用 -std=c11 选项(不使用它并没有改变任何结果)。发出的 x86 指令是 UCOMISS,它只会引发信号 NaN 的异常 - 我希望看到 COMISS 因为这会引发所有 NaN 比较的异常,因为无论它们是否发出信号,NaN 都是无序的。

我是否在代码中出错或忘记了某些编译器选项以使行为符合 IEEE 标准?忽略此处引发异常的需要可能是编译器中的错误(或性能优化)吗?

【问题讨论】:

FWIW 与 MSVC 的输出为“FE_INVALID”,c 为 0,尽管我注释掉了 pramga,因为它未被识别。 角落:确保feclearexcept(FE_ALL_EXCEPT);返回零。 检查__STDC_IEC_559__。 “定义_STDC_IEC_559_的实现应符合本附件中的规范。” (符合 IEEE 标准?)如果未定义 __STDC_IEC_559__,则未指定代码以按需要运行。只有错误才是错误的期望。 @WeatherVane 这很奇怪,但至少它对你有用 :) @chux 刚刚检查了feclearexcept,它返回 0。关于 IEEE 合规性也很好。 (Un)幸运的是,__STDC_IEC_559__ 已定义,所以问题出在其他地方.. 【参考方案1】:

好的,所以我冒险尝试运行最新的 GCC 版本 (8.2)。

代码在 GCC 8.2.0 下编译时的行为符合预期,因此我假设问题是编译器错误。我没有尝试 7.2.0 和 8.2 之间的其他版本来查看它从什么时候开始工作,但使用 8.2 对我来说已经足够了。

【讨论】:

以上是关于C:无序浮点比较不会引发 FE_INVALID的主要内容,如果未能解决你的问题,请参考以下文章

是否允许格式化输入/输出函数引发浮点异常?

c语言中将一个浮点型赋值给整型时,会不会四舍五入?

何时使用 C 浮点比较函数?

C/C++:浮点比较速度

在 C 代码的 printf 语句中使用时,不会显示浮点或双精度值

php7采坑记:浮点型数据比较