2

我知道使用该-ffast-math标志允许不安全的数学运算并禁用信号 NaN。isnan()但是,我希望这些功能isinf()仍然能够返回正确的结果,而他们没有。

这是一个例子:

文件test_isnan.c

#include <stdio.h>
#include <math.h>

int main(void){

  /* Produce a NaN */
  const float my_nan = sqrtf(-1.f);
  /* Produce an inf */
  const float my_inf = 1.f/0.f;

  printf("This should be a NaN: %.6e\n", my_nan);
  printf("This should be inf: %.6e\n", my_inf);

  if (isnan(my_nan)) {
    printf("Caugth the nan!\n");
  } else {
    printf("isnan failed?\n");
  }

  if (isinf(my_inf)) {
    printf("Caugth the inf!\n");
  } else {
    printf("isinf failed?\n");
  }
}

现在让我们在没有的情况下编译并运行程序-ffast-math

$ gcc test_isnan.c -lm -o test_isnan.o && ./test_isnan.o
This should be a NaN: -nan
This should be inf: inf
Caugth the nan!
Caugth the inf!

但有了它:

$ gcc test_isnan.c -lm -o test_isnan.o -ffast-math && ./test_isnan.o
This should be a NaN: -nan
This should be inf: inf
isnan failed?
isinf failed?

那么为什么不抓住这些s 和isnan()s呢?我错过了什么?isinf()naninf

如果它可能相关,这是我的gcc版本:

gcc (Spack GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4

2 回答 2

2

-ffast-数学

设置选项 ... -ffinite-math-only ...

-仅有限数学

允许对假设参数和结果不是 NaN或 +-Infs 的浮点算术进行优化。

编译器将代码优化为:

  printf("This should be a NaN: %.6e\n", sqrtf(-1.f));
  printf("This should be inf: %.6e\n", 1.f/0.f);
  printf("isnan failed?\n");
  printf("isinf failed?\n");

因为编译器知道表达式不能返回nanor inf

于 2021-10-06T10:03:38.357 回答
2

来自https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

-ffast-math
设置选项 -fno-math-errno、-funsafe-math-optimizations、-ffinite-math-only、-fno-rounding-math、-fno-signaling-nans、-fcx-limited-range 和 - fexcess-精度=快。

在哪里:

-ffinite-math-only允许对假设参数和结果不是 NaN 或 +-Infs
的浮点算术进行优化。

一旦你打破这个假设,你就不能指望这些功能起作用。

我了解您希望此设置能够优化所有其他操作,同时仍然为这两个函数提供正确的结果,但这不是它的工作方式。我认为没有办法解决这个问题。也许你可以看看 Clang,但我不认为它会有所不同。

于 2021-10-06T10:04:27.853 回答