C++如何处理NAN?有标准方式还是编译器依赖?

dgu*_*uan 18 c++ floating-point nan

在需要处理sin(x)/ x函数的程序中,我遇到了NAN问题,我简化了以下代码中的问题:

#include <iostream>
#include <cmath>

int main()
{
    std::cout.precision(15);

    //This line compiles and run in g++, but does not compile in Visual Studio 2013
    std::cout << 0.0/0.0 << std::endl;

    //This line compiles and run in both g++ and VS2013
    std::cout << std::sin(0.0)/0.0 << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在g ++中,输出为:-nan -nan,在VS2013中,输出为:-1.IND,因为第一行没有编译所以我把它注释掉了.

我的问题是:

  1. 这个'-1.IND'是什么意思?

  2. 似乎NAN处理依赖于编译器,这应该在C++中标准化吗?为什么?

  3. 我用这个hack来处理这个问题:

    double sinc(double x)
    {
        if(x == 0.0)
            return 1.0;
        return std::sin(x)/x;
    }
    
    Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?

编辑:另一个问题,4.为什么VS2013处理0.0/0.0和sin(0.0)/0.0不同?

nas*_*-sh 12

在SO上回答有类似的问题:

1.这个'-1.IND'是什么意思?

请参阅1.#INF00,-1.#IND00和-1.#IND是什么意思?

2.似乎NAN处理依赖于编译器,这应该在C++中标准化吗?为什么?

在C中看到关于除零的一些事情(它说C,但它谈到了C++)

我用这个黑客来处理这个问题:

double sinc(double x) {

    if(x == 0.0)
        return 1.0;
    return std::sin(x)/x; 
}
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?

是的,这个sinc函数的实现将起作用(感谢@MSalters的评论)在数学上是正确的; 但是,请记住,虽然它适用于这种情况,但不要养成比较double类型的习惯==.

  • 比较`double`s with` ==`在很多情况下是完全合理的.特别是这一个. (4认同)
  • @Nasser:也不是老手,但我认为现场链接(即其他SO答案)应该没问题.非现场链接更有可能消失. (3认同)
  • @Nasser没关系.所以不会破坏现场链接. (3认同)
  • @tmyklebu:'==`这里好的原因有点微妙但是:如果表达式是`sin(pi*x)/ x`那么对于库质量的实现你需要特殊情况subnormals,以避免'pi*x`中间结果的精度损失.所以有一个`if(abs(x)<1e-300)`式守卫代替平等是合适的.我们在这里没问题,因为`sin(x)`会为微小的`x`准确地给出'x`,没有明显的精度损失. (3认同)
  • @Nasser:`sinc(0)`被定义为1,在数学上它与规则中的C++相同.这不是限制. (2认同)

MSa*_*ers 5

为(4)添加答案,sin(x)是一个运行时函数,因此sin(0.0)/0.0作为在运行时计算的表达式处理.OTOH,0.0/0.0由编译器完全处理,这就是它发现问题的原因.Visual Studio版本的实现细节,而不是您可以计算的内容.