【问题标题】:Why is `isnan` returning 0 for a long double set to NAN?为什么 `isnan` 返回 0 的长双设置为 NAN?
【发布时间】:2021-01-30 02:58:15
【问题描述】:
#include <stdio.h>
#include <math.h>

int main()
{
    long double x = NAN;
    printf("x = %Lg\nisnan(x) = %d\n", x, isnan(x));
    return 0;
}

当我运行上面的程序时,我得到了输出:

x = nan
isnan(x) = 0

根据手册页,isnan 应该在参数为 NaN 时返回非零值。那么为什么它返回零呢?

【问题讨论】:

  • 使用选项“-fsignaling-nans”编译
  • @P__J__ 是的,我从您在另一条评论中发布的链接中发现了这一点,并将其编辑为我的答案。如果您将其发布为答案,我会接受(除非其他人发布了更好的答案。)

标签: c floating-point nan cmath long-double


【解决方案1】:

不确定这是否相关,但是...

$ gcc so64374723.c -lm && ./a.out x = 南 伊斯南(x) = 1 $ gcc -ffast-math so64374723.c -lm && ./a.out x = 南 伊斯南(x) = 0 $ gcc -fsignaling-nans so64374723.c -lm && ./a.out x = 南 伊斯南(x) = -1 $ clang -ffast-math so64374723.c -lm && ./a.out x = 南 伊斯南(x) = -1 $ clang so64374723.c -lm && ./a.out x = 南 伊斯南(x) = -1

【讨论】:

  • 你很亲密。 gcc.gnu.org/wiki/FloatingPointMath 。 gcc 必须与允许信号 NaN 的选项一起编译(大多数现代提供的 gcc 二进制文件都这样做)
  • 嗯...我使用的是旧版本的 gcc:6.3.0 20170516
【解决方案2】:

根据同一手册页,您应该在使用isnan 时“与-lm 链接”。将-lm 添加到gcc 命令行并重新编译后,isnan(x) 返回了应有的 1。

不知道为什么它之前没有给出链接器错误。我认为它要么不会在libm 之外实现,要么会正确实现。虽然我可能遗漏了一些东西。

编辑: 设置 -fsignaling-nans 也有效(感谢链接 @P__J__。)有趣的是,在这种情况下它返回 -1 而不是 1,但这仍然是正确的行为,因为它是一个非零值.

【讨论】:

  • 因为它是宏而不是函数。与链接器无关
  • @P__J__ 我知道这一点,但是如果我不与-lm 链接,为什么它不起作用?我认为宏可能在某种程度上使用了依赖于-lm 的东西,但我不知道如果它丢失了不会出错。
  • 它不能中继 libm 中的任何内容。否则,我们会得到链接器错误
猜你喜欢
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
相关资源
最近更新 更多