9

我知道JavaDouble.NaN是什么。我有一些 Java 代码可以生成NaN.

// 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

4 回答 4

41

NaN由以下事件触发:

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

很抱歉这样一个笼统的答案,但我希望这会有所帮助。

于 2010-05-22T06:19:24.847 回答
4

根据维基百科:

返回的操作有以下三种NaN

  • 以 aNaN作为至少一个操作数的操作
  • 不确定的形式
    • 分割 0/0、∞/∞、∞/-∞、-∞/∞ 和 -∞/-∞
    • 乘法 0×∞ 和 0×−∞
    • 幂 1 ∞</sup>
    • 加法 ∞ + (-∞)、(-∞) + ∞ 和等效减法。
  • 具有复杂结果的实际操作:
    • 负数的平方根
    • 负数的对数
    • 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"
    }
}

参考

于 2010-05-22T06:39:54.107 回答
3

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

于 2010-05-22T06:37:58.550 回答
0

您是否尝试过在代码中添加System.out.println语句以确定NaN的确切位置?

于 2010-05-22T06:09:36.087 回答