Когда Java может произвести NaN?

Я знаю что Java Double.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?

9
задан Eric Leschinski 22 June 2014 в 23:11
поделиться

4 ответа

Учитывая то, что я знаю о градиентном спуске, вы, скорее всего, выпрыгиваете в бесконечность, потому что у вас нет адаптивной скорости (т.е. ваша скорость слишком велика).

3
ответ дан 4 December 2019 в 06:09
поделиться

NaN запускается следующими событиями:

  • результаты, которые являются комплексными значениями
    • √x, где x отрицательно
    • log (x), где x отрицательно
    • tan (x), где x mod 180 равно 90
    • asin (x) или acos (x), где x находится вне [ -1..1]
  • 0/0
  • ∞ / ∞
  • ∞ / −∞
  • −∞ / ∞
  • −∞ / −∞
  • 0 × ∞
  • 0 × −∞
  • 1
  • ∞ + (−∞)
  • (- ∞) + ∞

Извините за такой общий ответ, но я надеюсь, что это помогло.

37
ответ дан 4 December 2019 в 06:09
поделиться

Пробовали ли вы посыпать ваш код System.out.println утверждениями, чтобы определить точно, где начинают возникать NaNs?

0
ответ дан 4 December 2019 в 06:09
поделиться

Согласно Википедии:

Существует три вида операций, возвращающих 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"
    }
}

Ссылки

  • Wikipedia/NaN
  • JLS 15.21. 1 Операторы числового равенства == и !=

    Если один из операндов равен NaN, то результат == равен false, а результат != равен true. Действительно, тест x!=x является истинным тогда и только тогда, когда значение x равно NaN. (Методы Float.isNaN и Double.isNaN также могут использоваться для проверки того, является ли значение NaN).

4
ответ дан 4 December 2019 в 06:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: