Вопрос
У меня есть программа, которая пытается уменьшить double
вплоть до желаемого числа.Результат, который я получаю, таков NaN
.
Что делает NaN
имеете в виду на Java?
Решение
Взято из эта страница:
«Нан» означает «не число». «NAN» производится, если операция с плавающей точкой имеет некоторые входные параметры, которые вызывают операцию для получения некоторого не определенного результата. Например, 0,0, разделенный на 0,0, арифметически неопределен. Взятие квадратного корня отрицательного числа также не определено.
Другие советы
NaN
означает «Не число» и в основном является представлением специального значения плавающего точка в IEE 754 Плавающая точка стандартный Нан Как правило, означает, что значение - это то, что нельзя выразить с действительной с плавающей запятой.
Преобразование приведет к этому значению, когда преобразованное значение является чем-то еще, например, при преобразовании строки, которая не представляет число.
NaN
означает «не число» и является результатом неопределенных операций на количестве с плавающей точкой, как, например, разделяться ноль на ноль. (Обратите внимание, что при разделении ненулевого номера на ноль также обычно не определено в математике, он не приводит к NAN, а в положительной или отрицательной бесконечности).
NaN
означает «не число». Это специальное значение плавающего точка, которое означает, что результат операции не был определен или не представлен в качестве реального числа.
Видеть здесь Для более объяснения этого значения.
Нэн стоит не число. Используется для обозначения любого значения, которое математически неопределено. Как разделить 0,0 на 0,0. Вы можете посмотреть здесь для получения дополнительной информации: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm.
Опубликуйте свою программу здесь, если вам нужна дополнительная помощь.
Nan = не число.
Означает не число. Это общее представление для невозможного числового значения во многих языках программирования.
Не Java Guy, но в JS и других языках я использую его «не число», что означает, что некоторые операции привели к тому, что она стала не действительным числом.
Это буквально означает «не число». Я подозреваю, что что-то не так с вашим процессом преобразования.
Проверьте раздел не число в Эта ссылка
Не допустимое значение плавающего точка (например, результат разделения на ноль)
Минимальный выполнимый пример
Первое, что вы должны знать, это то, что концепция NaN реализована непосредственно на аппаратном обеспечении центрального процессора.
Похоже, что все основные современные процессоры следуют IEEE 754 который определяет форматы с плавающей запятой, и NAN, которые являются просто специальными значениями с плавающей запятой, являются частью этого стандарта.
Таким образом, концепция будет очень схожей на любом языке, включая Java, который просто передает код с плавающей запятой непосредственно в центральный процессор.
Прежде чем продолжить, возможно, вы захотите сначала прочитать следующие ответы, которые я написал:
- быстрое обновление формата IEEE 754 с плавающей запятой: Что такое ненормальное число с плавающей запятой?
- некоторые основы NaN более низкого уровня, описанные с использованием C / C ++: В чем разница между тихим NaN и сигнальным NaN?
Теперь перейдем к некоторым действиям 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));
}
}
Бегите с:
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
чтобы обнаружить их, но я не думаю, что это доступно в Java: Почему целочисленное деление на ноль 1/0 выдает ошибку, но с плавающей запятой 1/0.0 возвращает "Inf"?странные операции, которые находятся на пределе либо плюс, либо минус бесконечности, однако дают +- бесконечность вместо NaN
1.0f / 0.0f
log(0.0f)
0.0
почти подпадает под эту категорию, но, вероятно, проблема в том, что оно могло перейти либо в плюс, либо в минус бесконечность, поэтому было оставлено как NaN.если NaN является входным сигналом плавающей операции, то выходные данные также имеют тенденцию быть NaN
существует несколько возможных значений для NaN
0x7fc00000
,0x7fc00001
,0x7fc00002
, хотя x86_64 , кажется , генерирует только0x7fc00000
.NaN и infinity имеют аналогичное двоичное представление.
Давайте разберем некоторые из них:
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.Таким образом, существует несколько возможностей, за исключением мантиссы == 0, которая равна бесконечности
NANS может быть как положительным, так и отрицательным (верхний бит), хотя это никак не влияет на нормальную работу
Протестировано в Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.