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 です
    • x が [-1..1] の外側にある asin(x) または acos(x)
  • 0/0
  • ∞/∞</li>
  • ∞/−∞
  • −∞/∞</li>
  • −∞/−∞
  • 0×∞</li>
  • 0×−∞
  • 1 ∞</sup>
  • ∞ + (−∞)
  • (−∞) + ∞</li>

このような一般的な回答で申し訳ありませんが、お役に立てば幸いです。

于 2010-05-22T06:19:24.847 に答える
4

ウィキペディアによると:

次の 3 種類の操作がありますNaN

  • NaN少なくとも 1 つのオペランドとしてaを使用する演算
  • 不定形
    • 除算 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"
    }
}

参考文献

  • ウィキペディア/NaN
  • JLS 15.21.1 数値等価演算子 == および !=

    いずれかのオペランドがNaNである場合、 is の結果は==is ですfalseが、 is の結果!=ですtrue。実際、テストx!=xtrueの値が である場合にのみ有効xですNaN。(メソッドFloat.isNaNDouble.isNaNは、値が であるかどうかをテストするためにも使用できますNaN。)

于 2010-05-22T06:39:54.107 に答える
3

rate勾配降下について私が知っていることを考えると、適応性がない(つまり、rate大きすぎる)ため、おそらく無限大に飛び出しています。

于 2010-05-22T06:37:58.550 に答える
0

NaN が発生し始める場所を正確System.out.printlnに特定するステートメントをコードに散りばめてみましたか?

于 2010-05-22T06:09:36.087 に答える