C ++中NaN的异常原因? NaN接近零的限制会导致NaN吗?

时间:2013-07-21 22:16:59

标签: c++ neural-network nan tracing

在处理涉及神经网络的C ++项目时,我受到NaN结果的阻碍。经过大量的追踪(试图找到NaN的起源),我意识到它的来源是我的S形导数函数,如下所示。

double sigDer(double n){
    return 2*exp(-n) / pow(1 + exp(-n), 2);
}

虽然它具有所有实数的域,但-1008.3等值会导致NaN的结果。根据mathematica,正确的结果应该非常接近零 - 2.522 * 10 ^ -438。我以下列方式避免了这个问题:

double sigDer(double n){
    double res = 2*exp(-n) / pow(1 + exp(-n), 2);
    if( isnan(res) ){
        return 0;
    } else{
        return res;
    }
} 

通过这个简单的假设,我的代码按预期运行;但是,我仍然不明白为什么sigDer(< #with large magnitude>)不会返回〜0。有人可以告诉我C ++(Xcode IDE)中NaN的原因除了除以零并取消负的均匀根吗?

提前致谢!我还想知道为什么签名者(-1008.3)返回NaN以及如何更好/更有效地追踪NaN值的来源。

3 个答案:

答案 0 :(得分:3)

好吧,如果分子和分母最终都为0,那么你正在做0/0,即NaN。

我还没有完成计算,但我想exp(-1008)小于2E-308,即double中最小的可表示值。

  

有人可以告诉我NaN的原因

Wikpedia has this covered.

答案 1 :(得分:2)

limes

每种情况下的分母都试图达到无穷大(这意味着整个分数都试图达到0)。但是,这意味着您要通过无穷大来定义某个除法(与有限的双倍范围相结合)。

这里的解释在于c++ exp function,如果返回值不能表示为double,则返回+ -HUGE_VAL。

话虽如此,当你的结果不能包含在一个双变量中时,它会导致除以无穷大,从而导致 nan

顺便说一句,如果你想操作大数字,你可以实现一个存储数字的类,例如字符串和重载运算符。

答案 2 :(得分:1)

如果您的输入n是一个较大的否定数字

exp(-n) -> inf

pow(1 + exp(-n), 2) -> pow(1 + inf, 2) -> inf

inf / inf -> nan

如果您的输入n是一个很大的数字,那么您永远不会得到nan 0/0

pow(1 + exp(-n), 2) -> pow(1 + 0, 2) != 0