Подтвердить что ты не робот

В Java, что означает NaN?

У меня есть программа, которая пытается сжать double до нужного числа. Выход, который я получаю, равен NaN.

Что означает NaN в Java?

4b9b3361

Ответ 1

Взято из эта страница:

"NaN" означает "не число". "Нан" производится, если с плавающей точкой операция имеет некоторые входные параметры которые приводят к некоторый результат undefined. Например, 0.0, деленная на 0,0, арифметически undefined. Принимая квадратный корень из отрицательное число также undefined.

Ответ 2

NaN означает "не число" и является в основном представлением специального значения с плавающей запятой в стандарте IEE 754. Обычно NaN означает, что это значение не может быть выражено с помощью действительного числа с плавающей запятой.

Преобразование приведет к этому значению, когда преобразованное значение является чем-то другим, например, при преобразовании строки, которая не представляет число.

Ответ 3

NaN означает "Не число" и является результатом операций undefined для чисел с плавающей запятой, например, например, деления нуля на ноль. (Заметим, что при делении ненулевого числа на ноль также обычно undefined в математике, это не приводит к NaN, а в положительной или отрицательной бесконечности).

Ответ 4

NaN означает "Не число". Это специальное значение с плавающей запятой, которое означает, что результат операции не был определен или не может быть представлен как действительное число.

Смотрите здесь для более подробного объяснения этого значения.

Ответ 5

NaN означает не число. Он используется для обозначения любого значения, которое математически undefined. Как деление 0.0 на 0.0. Вы можете посмотреть здесь для получения дополнительной информации: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm

Отправьте свою программу здесь, если вам нужна дополнительная помощь.

Ответ 6

NaN = не номер.

Ответ 7

означает не число. Это общее представление о невозможном числовом значении во многих языках программирования.

Ответ 8

Не парень Java, но в JS и других языках я использую его "Not a Number", что означает, что некоторая операция заставила его стать недопустимым.

Ответ 9

Это буквально означает "Не номер". Я подозреваю, что что-то не так с процессом преобразования.

Посмотрите раздел "Не номер" в эта ссылка

Ответ 10

Недействительное значение с плавающей запятой (например, результат деления на ноль)

http://en.wikipedia.org/wiki/NaN

Ответ 11

Минимальный исполняемый пример

Первое, что вы должны знать, это то, что концепция NaN реализована непосредственно на оборудовании ЦП.

Все основные современные процессоры, похоже, следуют IEEE 754, который определяет форматы с плавающей запятой, а NaN, которые являются просто специальными значениями с плавающей запятой, являются частью этого стандарта.

Следовательно, концепция будет очень похожа на любой язык, включая Java, который просто передает код с плавающей запятой непосредственно в ЦП.

Прежде чем продолжить, вы можете сначала прочитать следующие ответы, которые я написал:

Теперь для некоторых действий Java. Большинство интересующих функций, которых нет в основном языке, живут внутри java.lang.Float.

Nan.java

import java.lang.Float;
import java.lang.Math;

public class Nan {
    public static void main(String[] args) {
        // Generate some NaNs.
        float nan            = Float.NaN;
        float zero_div_zero  = 0.0f / 0.0f;
        float sqrt_negative  = (float)Math.sqrt(-1.0);
        float log_negative   = (float)Math.log(-1.0);
        float inf_minus_inf  = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
        float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
        float quiet_nan1     = Float.intBitsToFloat(0x7fc00001);
        float quiet_nan2     = Float.intBitsToFloat(0x7fc00002);
        float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
        float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
        float nan_minus      = -nan;

        // Generate some infinities.
        float positive_inf   = Float.POSITIVE_INFINITY;
        float negative_inf   = Float.NEGATIVE_INFINITY;
        float one_div_zero   = 1.0f / 0.0f;
        float log_zero       = (float)Math.log(0.0);

        // Double check that they are actually NaNs.
        assert  Float.isNaN(nan);
        assert  Float.isNaN(zero_div_zero);
        assert  Float.isNaN(sqrt_negative);
        assert  Float.isNaN(inf_minus_inf);
        assert  Float.isNaN(inf_times_zero);
        assert  Float.isNaN(quiet_nan1);
        assert  Float.isNaN(quiet_nan2);
        assert  Float.isNaN(signaling_nan1);
        assert  Float.isNaN(signaling_nan2);
        assert  Float.isNaN(nan_minus);
        assert  Float.isNaN(log_negative);

        // Double check that they are infinities.
        assert  Float.isInfinite(positive_inf);
        assert  Float.isInfinite(negative_inf);
        assert !Float.isNaN(positive_inf);
        assert !Float.isNaN(negative_inf);
        assert one_div_zero == positive_inf;
        assert log_zero == negative_inf;
            // Double check infinities.

        // See what they look like.
        System.out.printf("nan            0x%08x %f\n", Float.floatToRawIntBits(nan           ), nan           );
        System.out.printf("zero_div_zero  0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
        System.out.printf("sqrt_negative  0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
        System.out.printf("log_negative   0x%08x %f\n", Float.floatToRawIntBits(log_negative  ), log_negative  );
        System.out.printf("inf_minus_inf  0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
        System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
        System.out.printf("quiet_nan1     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1    ), quiet_nan1    );
        System.out.printf("quiet_nan2     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2    ), quiet_nan2    );
        System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
        System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
        System.out.printf("nan_minus      0x%08x %f\n", Float.floatToRawIntBits(nan_minus     ), nan_minus     );
        System.out.printf("positive_inf   0x%08x %f\n", Float.floatToRawIntBits(positive_inf  ), positive_inf  );
        System.out.printf("negative_inf   0x%08x %f\n", Float.floatToRawIntBits(negative_inf  ), negative_inf  );
        System.out.printf("one_div_zero   0x%08x %f\n", Float.floatToRawIntBits(one_div_zero  ), one_div_zero  );
        System.out.printf("log_zero       0x%08x %f\n", Float.floatToRawIntBits(log_zero      ), log_zero      );

        // NaN comparisons always fail.
        // Therefore, all tests that we will do afterwards will be just isNaN.
        assert !(1.0f < nan);
        assert !(1.0f == nan);
        assert !(1.0f > nan);
        assert !(nan == nan);

        // NaN propagate through most operations.
        assert Float.isNaN(nan + 1.0f);
        assert Float.isNaN(1.0f + nan);
        assert Float.isNaN(nan + nan);
        assert Float.isNaN(nan / 1.0f);
        assert Float.isNaN(1.0f / nan);
        assert Float.isNaN((float)Math.sqrt((double)nan));
    }
}

GitHub вверх по течению.

Бежать с:

javac Nan.java && java -ea Nan

Выход:

nan            0x7fc00000 NaN
zero_div_zero  0x7fc00000 NaN
sqrt_negative  0xffc00000 NaN
log_negative   0xffc00000 NaN
inf_minus_inf  0x7fc00000 NaN
inf_times_zero 0x7fc00000 NaN
quiet_nan1     0x7fc00001 NaN
quiet_nan2     0x7fc00002 NaN
signaling_nan1 0x7fa00001 NaN
signaling_nan2 0x7fa00002 NaN
nan_minus      0xffc00000 NaN
positive_inf   0x7f800000 Infinity
negative_inf   0xff800000 -Infinity
one_div_zero   0x7f800000 Infinity
log_zero       0xff800000 -Infinity

Итак, из этого мы узнаем несколько вещей:

  • странные плавающие операции, которые не имеют никакого разумного результата, дают NaN:

    • 0.0f/0.0f
    • sqrt(-1.0f)
    • log(-1.0f)

    генерировать NaN.

    В C на самом деле можно запросить сигналы, которые должны быть feenableexcept в таких операциях с помощью feenableexcept за feenableexcept их обнаружения, но я не думаю, что это проявляется в Java: почему целочисленное деление на ноль 1/0 дает ошибку, но с плавающей запятой 1/0.0 возвращает "Инф"?

  • странные операции, которые находятся на пределе плюс или минус бесконечность, однако дают + - бесконечность вместо NaN

    • 1.0f/0.0f
    • log(0.0f)

    0.0 почти попадает в эту категорию, но, скорее всего, проблема в том, что он может перейти в плюс или минус бесконечность, поэтому он был оставлен как NaN.

  • если NaN является входом плавающей операции, выход также имеет тенденцию быть NaN

  • Есть несколько возможных значений для NaN 0x7fc00000, 0x7fc00001, 0x7fc00002, хотя x86_64, кажется, генерирует только 0x7fc00000.

  • NaN и бесконечность имеют одинаковое двоичное представление.

    Давайте разберем несколько из них:

    nan          = 0x7fc00000 = 0 11111111 10000000000000000000000
    positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
    negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
                                | |        |
                                | |        mantissa
                                | exponent
                                |
                                sign
    

    Исходя из этого, мы подтверждаем, что IEEE754 указывает:

    • и NaN, и бесконечности имеют показатель степени == 255 (все единицы)
    • у бесконечностей есть мантисса == 0. Следовательно, возможны только две бесконечности: + и 0, дифференцированные знаковым битом
    • У NaN есть мантисса! = 0. Поэтому есть несколько возможностей, кроме мантиссы == 0, которая равна бесконечности
  • NaN могут быть как положительными, так и отрицательными (верхний бит), хотя это не влияет на нормальные операции

Протестировано в Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.