Java什么时候可以产生NaN?

时间:2010-05-22 06:07:20

标签: java nan

我知道Java Double.NaN是什么。我有一些生成NaN的Java代码。

// calculate errors
delta = m1 + m2 - M;
eta = f1 + f2 - F;
for (int i = 0; i < numChildren; i++) {
  epsilon[i] = p[i]*m1+(1-p[i])*m2+q[i]*f1+(1-q[i])*f2-C[i];
}

// use errors in gradient descent
// set aside differences for the p's and q's
float mDiff = m1 - m2;
float fDiff = f1 - f2;
// first update m's and f's
m1 -= rate*delta;
m2 -= rate*delta;
f1 -= rate*eta;
f2 -= rate*eta;
for (int i = 0; i < numChildren; i++) {
  m1 -= rate*epsilon[i]*p[i];
  m2 -= rate*epsilon[i]*(1-p[i]);
  f1 -= rate*epsilon[i]*q[i];
  f2 -= rate*epsilon[i]*(1-q[i]);
}
// now update the p's and q's
for (int i = 0; i < numChildren; i++) {
  p[i] -= rate*epsilon[i]*mDiff;
  q[i] -= rate*epsilon[i]*fDiff;  
}

在什么情况下Java会产生NaN值?

4 个答案:

答案 0 :(得分:35)

NaN由以下事件触发:

  • 结果是复杂的值
    • √x其中x为负
    • log(x)其中x为负
    • tan(x)其中x mod 180是90
    • asin(x)或acos(x)其中x在[-1..1]
    • 之外
  • 0/0
  • ∞/∞
  • ∞/-∞
  • -∞/∞
  • -∞/-∞
  • 0×∞
  • 0×-∞
  • 1
  • ∞+(-∞)
  • ( - ∞)+∞

很抱歉这么一般的答案,但我希望有所帮助。

答案 1 :(得分:4)

根据维基百科:

  

有三种操作返回NaN

     
      
  • 使用NaN作为至少一个操作数的操作
  •   
  • 不确定表格      
        
    • 划分0/0,∞/∞,∞/-∞,-∞/∞和-∞/-∞
    •   
    • 乘法0×∞和0×-∞
    •   
    • 权力1
    •   
    • 加法∞+( - ∞),( - ∞)+∞和等效减法。
    •   
  •   
  • 结果复杂的实际操作:      
        
    • 负数的平方根
    •   
    • 负数的对数
    •   
    • 90度(或π/ 2弧度)的奇数倍的切线
    •   
    • 小于-1或大于+1的数字的反正弦或余弦。
    •   
  •   

这个Java片段说明了上述所有内容,除了切线之外(我怀疑是因为double的精度有限):

import java.util.*;
import static java.lang.Double.NaN;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.lang.Double.NEGATIVE_INFINITY;

public class NaN {
    public static void main(String args[]) {
        double[] allNaNs = {
            0D/0D,
            POSITIVE_INFINITY / POSITIVE_INFINITY,
            POSITIVE_INFINITY / NEGATIVE_INFINITY,
            NEGATIVE_INFINITY / POSITIVE_INFINITY,
            NEGATIVE_INFINITY / NEGATIVE_INFINITY,
            0 * POSITIVE_INFINITY,
            0 * NEGATIVE_INFINITY,
            Math.pow(1, POSITIVE_INFINITY),
            POSITIVE_INFINITY + NEGATIVE_INFINITY,
            NEGATIVE_INFINITY + POSITIVE_INFINITY,
            POSITIVE_INFINITY - POSITIVE_INFINITY,
            NEGATIVE_INFINITY - NEGATIVE_INFINITY,
            Math.sqrt(-1),
            Math.log(-1),
            Math.asin(-2),
            Math.acos(+2),
        };
        System.out.println(Arrays.toString(allNaNs));
        // prints "[NaN, NaN...]"
        System.out.println(NaN == NaN); // prints "false"
        System.out.println(Double.isNaN(NaN)); // prints "true"
    }
}

参考

答案 2 :(得分:3)

鉴于我对梯度下降的了解,你很可能会跳到无穷大,因为你没有自适应rate(即你的rate太大了。)

答案 3 :(得分:0)

您是否尝试使用System.out.println语句填充代码以确定确切 NaN何时开始发生?