【问题标题】:How to check quiet NaN in gcc?如何在 gcc 中检查安静的 NaN?
【发布时间】:2012-09-25 05:42:08
【问题描述】:

我知道 if(value==value) 可以解决问题,但在我的应用程序中,我需要检查 50 多个变量,并且检查每个变量有点乏味并且可能效率低下。理想情况下,我正在寻找的是在子程序结束之前我可以调用一个函数(如果存在这样的函数),它将返回 1 或 0。我有一种感觉,因为在汇编中存在这样一个可以检查全局浮动的函数点状态寄存器。 如果不是这种情况,那么有没有比轮询每个浮点变量的 value==value 更好的方法?

【问题讨论】:

  • 你怎么能在 C 中得到 NaN 呢?
  • @Eregrith:sqrt(-1)log(-1)0. / 0
  • 您想知道其中 any 是否是 NaN?如果是这样,也许isnan(var1 + var2 + var3 + ...)。但不要相信我的话,首先检查它是否会产生误报,如果会,它们对你是否重要。例如可能+INF + -INFNaN,我不记得了。顺便说一句,这里真正的问题是您要检查 50 个变量——通常您会使用多个值执行一些计算,并且只关心 result 是否为 NaN。安静 NaN 的意义在于它可以传播。有些人甚至会说任何一个函数中的 50 个变量都是错误的。
  • 我知道,但我正在更新一些外部供应商的固件,所以我对此无能为力,但求和是个好主意;我会看看情况如何。
  • 其实isnan是C语言中的一个宏,不是吗?因此,如果这对您来说还不是很明显:我写的确切表达式不好,它可能会计算两次总和。

标签: c gcc floating-point nan


【解决方案1】:

也许这样的事情可能会有所帮助?

void registerAddVariable(double *x) {
  APPEND(x); // append to some global linked list
}
void registerRemoveVariable(double *x) {
  REMOVE(x); // remove from same global linked list
}
void registerDebug() {
  list = head; 
  while(list) {
    if (isnan(*(list->variable))) {
      output(list);
    }
    list = list->next;
  }
}

void myfun() {
  double variable; registerAddVariable(&variable);
  ...
  registerDebug();
  ....
  registerRemoveVariable(&variable);
}

【讨论】:

    【解决方案2】:

    一般来说,没有办法问“我的数据中是否有 NaN?”

    检查处理器的浮点寄存器不足以回答这个问题,因为浮点对象的值保存在内存以及计算的各个点的寄存器中,特别是如果您有 50 个。

    有一种方法可以询问“是否发生了无效操作异常?” C 标准的第 7.6 条通过定义在 .各种编译器对它的支持可能很差。本质上,您可能希望使用 feclearexcept 清除 FE_INVALID,执行一些计算,并测试是否已使用 fetestexcept 设置了 FE_INVALID。您还需要设置“#pragma STD FENV_ACESS on”。

    这只会测试在您的计算过程中是否发生了无效操作异常。它不会测试您的输入数据中是否存在 NaN。它不会测试在没有无效操作异常的情况下生成的 NaN。

    【讨论】:

      【解决方案3】:

      您可以使用isnanfpclassify。两者都是 C99 中的标准。

      至于您的问题,如果您的变量都在某个公共位置声明,我会编写一个小工具将这些声明转换为 isnan 调用字符串。

      【讨论】:

      • 谢谢,但这并不能解决我的问题。我仍然需要在我的所有变量上调用 isnan。
      • @AlexandreC。循环函数中的所有double 变量?我想你可以先创建一个指向它们的指针数组,然后循环遍历它。我认为我们三个人都有相同的抱怨,即 50 个变量就是错误的,但这并不一定意味着 Arunav 可以在解决眼前的问题之前先解决这个问题。
      • @SteveJessop:确实,指针表是一种可怕的解决方案。实际上,这完全取决于现有的实现:可能是 Arunav 可以让 NaN 冒泡,直到它们被实际使用并且可以检查。也可以在某个公共位置声明变量,然后编写一个小解析器,将这些声明转换为一堆 isnan 调用。
      猜你喜欢
      • 2015-09-23
      • 2012-01-01
      • 2022-01-13
      • 1970-01-01
      • 2010-10-30
      相关资源
      最近更新 更多