assert (!isnan(x)) 成功,但 printf("%f",x) 显示 -nan

问题描述 投票:0回答:2

我正在使用 gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0。

我的代码中有一个错误,其中数值分析函数给出了非常不同的答案。 以下每个都返回 true。 x 是双精度数。

    assert (fpclassify(x) == FP_NORMAL);;
    assert (x == x);
    assert (!(isnan(x)));
    assert (isnormal(x));

    uint64_t abc = *((long long*)&x) ;
    printf("%" PRIx64 "\n", abc);
    /* Prints fff8000000000000 */
    printf("%f",x);
    /* Prints -nan */
    uint64_t x4 = 0xfff8000000000000;
    assert (x4 == abc);
    

我从 OCaml 调用 C 代码,因此 OCaml 运行时可能会弄乱这些值。

这可能是编译器错误还是有其他解释?

编辑:这篇文章的先前版本错误地使用了按位否定而不是布尔否定。

c ocaml nan
2个回答
1
投票

~
运算符是按位补码——它翻转值的所有位——不是逻辑非。 因此,将其应用于“布尔”值很少会达到您想要的效果。 例如程序:

#include <stdbool.h>
#include <stdio.h>

int main() {
    if (~true) {
        printf("~true is true\n");
    }
}

将打印

~true is true


1
投票

每个

issomething
浮点分类宏“当且仅当其参数”位于测试类别中时返回非零值(7.12.3 中的 C 2018 子条款)。所以它不一定产生 0 或 1。它可能产生 2、4 或其他数字。

当您对这些值应用按位求补运算符

~
时,零值将产生非零结果,但 1、2、4 和大多数其他值也将产生非零结果;结果将关闭操作数中打开的位,但打开关闭的位,通常会产生一个非零数字。

对于二进制补码,只有等于

~0
, −1 的值才会产生零结果。

要测试

isnormal
的逆,您可以使用布尔否定:
!isnormal(x)

© www.soinside.com 2019 - 2024. All rights reserved.