Как NaN и бесконечность float или double хранятся в памяти?

Насколько я понимаю, java будет хранить в памяти число с плавающей запятой как 32-битное целое число со следующими свойствами:

  • Первый бит используется для определения знака
  • Следующие 8 бит представляют собой показатель степени
  • Последние 23 бита используются для хранения дроби

Это не оставляет лишних битов для трех особых случаев:

  • NaN
  • Положительная бесконечность
  • Отрицательная бесконечность

Я могу предположить, что отрицательный 0 может использоваться для хранения одного из них.

Как они на самом деле представлены в памяти?


person roblovelock    schedule 22.03.2016    source источник
comment
Это записано в постоянном описании 0xfff0000000000000L=-Infinity, 0x7ff0000000000000L=+Infinity и 0x7ff8000000000000L=NaN. (Это значения для double)   -  person SomeJavaGuy    schedule 22.03.2016
comment
это задокументировано в javadoc   -  person wero    schedule 22.03.2016
comment
Отрицательный ноль на самом деле тоже существует как отдельная вещь.   -  person harold    schedule 22.03.2016
comment
См. Также: stackoverflow.com/questions/2154484 / stackoverflow.com/questions/25050133/   -  person MSalters    schedule 22.03.2016
comment
@Lashane Первая ссылка в Google - это этот вопрос: google.com/search?q=how+are+NaN+and+infinity+stored+in+memory IMO плохо изучил или нет вопросы, подобные этому, часто невероятно полезны.   -  person Ajedi32    schedule 22.03.2016
comment
Эквивалентный вопрос для fortran: stackoverflow.com/q/640109/1157054   -  person Ajedi32    schedule 22.03.2016
comment
@ Ajedi32 Мне не хватает твоей точки зрения   -  person Iłya Bursov    schedule 22.03.2016
comment
@Lashane Я хочу сказать, что независимо от количества исследовательских усилий, направленных на изучение этого вопроса, он по-прежнему очень полезен и вполне может помочь сотням, тысячам или даже десяткам тысяч людей в течение следующих нескольких лет. И это достойно признания. Другие примеры таких вопросов включают некоторые из самых популярных вопросов на сайте, такие как stackoverflow.com/q/231767/1157054, stackoverflow.com/q/1789945/1157054, stackoverflow.com/q/79923/1157054 и т. д.   -  person Ajedi32    schedule 22.03.2016
comment
@ Ajedi32 Итак, старый вопрос должен быть одобрен, а этот закрыт как дубликат, также обратите внимание - правила этого сайта изменились, поэтому некоторые старые вопросы теперь не по теме, но все еще здесь по историческим причинам   -  person Iłya Bursov    schedule 22.03.2016
comment
@Lashane Я бы согласился, если бы этот вопрос был дубликатом, но пока кажется, что это не так. Отчасти это и делает его таким полезным - по-видимому, никто раньше явно не спрашивал в SO о том, как именно таким образом в памяти хранятся числа с плавающей запятой. В любом случае, вопросы, которые я связал, не закрыты и не заблокированы. Это хорошие вопросы по теме, и этот тоже.   -  person Ajedi32    schedule 22.03.2016
comment
@ Ajedi32 Итак, теперь мы должны ожидать 2 ^ 64 явных вопросов, как float 1.0 представлен в памяти? Каким образом double 1.0 представлен в памяти?   -  person Iłya Bursov    schedule 22.03.2016
comment
stackoverflow.com/questions/10528730/   -  person Iłya Bursov    schedule 22.03.2016
comment
Позвольте нам продолжить это обсуждение в чате.   -  person Ajedi32    schedule 22.03.2016
comment
@ Ajedi32 Вы, конечно же, не утверждаете, что вопрос, заданный 10 часов назад, сначала появляется в Google из-за ссылок, идущих с сайтов, не относящихся к SO? Нет, в Google он стоит на первом месте, потому что находится на SO, сайте с (обычно) качественным содержанием. Так и оставим. Вы знаете, какой еще сайт имеет качественное содержание и поднялся бы первым, если бы не этот вопрос? Википедия: en.wikipedia.org/wiki/NaN   -  person Pascal Cuoq    schedule 22.03.2016
comment
@PascalCuoq Нет, я говорю, что неправильно говорить, что вопрос бесполезен только потому, что ответ можно найти, прочитав другие источники. До того, как этот вопрос был опубликован, людям, выполняющим поиск в Google, возможно, пришлось прочитать статью в Википедии о NaN, чтобы найти ответ на него. Теперь вместо этого полный, хорошо написанный ответ на их конкретный вопрос можно найти в верхней части результатов поиска Google, что, на мой взгляд, в целом лучше. Задавайте вопросы, получайте ответы, не отвлекаясь   -  person Ajedi32    schedule 23.03.2016


Ответы (5)


Java определяет, что числа с плавающей запятой соответствуют стандарту IEEE 754.

Вот как он хранится:

  • бит 0: знаковый бит
  • биты с 1 по 11: показатель степени
  • биты с 12 по 63: дробь

Теперь я выполнил метод ниже с разными двойными значениями:

public static void print(double d){
    System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d)));
}

Я выполнил эти значения:

print(Double.NaN);
print(Double.NEGATIVE_INFINITY);
print(Double.POSITIVE_INFINITY);
print(-Double.MAX_VALUE);
print(Double.MAX_VALUE);

И получил следующий вывод для значений выше (отформатирован для удобства чтения):

 NaN: 0111111111111000000000000000000000000000000000000000000000000000
-Inf: 1111111111110000000000000000000000000000000000000000000000000000
+Inf: 0111111111110000000000000000000000000000000000000000000000000000
-Max: 1111111111101111111111111111111111111111111111111111111111111111
+Max: 0111111111101111111111111111111111111111111111111111111111111111

Википедия объясняет, что когда в поле экспоненты задано все биты-1, число - либо Inf, либо NaN. Inf имеет все биты нулевой мантиссы; NaN имеет хотя бы один бит мантиссы, равный 1. Знаковый бит сохраняет свое обычное значение для Inf, но не имеет значения для NaN. Double.NaN в Java - это одно конкретное значение, которое будет интерпретироваться как NaN, но есть еще 2 53 3 других.

person Darshan Mehta    schedule 22.03.2016
comment
Пожалуйста, либо напишите фактический результат, который вы получили из своего кода, который в его нынешнем виде никогда не печатает текст, а только двоичный, либо обновите свой код, чтобы напечатать то, что вы говорите. Кроме того, поскольку сложно быстро сравнивать в нынешнем виде, пожалуйста, выровняйте числа. - person Fund Monica's Lawsuit; 22.03.2016
comment
Вам по-прежнему не удается упростить сравнение результатов, что может сделать код, который вы в настоящее время даете. Пожалуйста, напишите фактический вывод этого кода или включите код, который будет генерировать вывод, который вы дадите. - person Fund Monica's Lawsuit; 22.03.2016
comment
Как я сказал ранее, код и форматированный вывод не требуют пояснений. Что я не могу понять, так это понять приведенный выше комментарий. Если у вас есть какой-либо конкретный вопрос, вы можете задать его как новый вопрос по SO, и я буду рад ответить. Ваше здоровье. - person Darshan Mehta; 22.03.2016
comment
Хорошо, я отредактирую, чтобы показать, что я имею в виду, когда буду за компьютером. Не стесняйтесь откатывать его, если не согласны. У меня нет вопросов; Я пытаюсь заставить вас улучшить свой ответ. - person Fund Monica's Lawsuit; 22.03.2016
comment
Я исправил ваш вывод и вашу интерпретацию вывода. Ваш фактический код печати, каким бы он ни был, ввел вас в заблуждение, отбросив начальные нулевые биты, заставив вас подумать, что бит знака был установлен для всего. - person zwol; 22.03.2016

Из здесь:

В. Как представлены ноль, бесконечность и NaN с помощью IEEE 754?

A. Установив все биты экспоненты в 1. Положительная бесконечность = 0x7ff0000000000000 (все биты экспоненты 1, бит знака 0 и все биты мантиссы 0), отрицательная бесконечность = 0xfff0000000000000 (все биты экспоненты 1, бит знака 1 и все биты мантиссы 0) , NaN = 0x7ff8000000000000 (все биты экспоненты 1, установлен хотя бы один бит мантиссы). Положительный ноль = все биты 0. Отрицательный ноль = все биты 0, кроме бита знака, который равен 1.

Также обратитесь к документации Javadocs о NAN, положительной бесконечности и отрицательная бесконечность.

person Rahul Tripathi    schedule 22.03.2016
comment
Это также означает, что может быть несколько NaN, которые можно отличить друг от друга (даже если все они NaN). Некоторые приложения используют это для хранения дополнительной информации о природе не числа. - person Joey; 22.03.2016

Как описано в Wikipedia, показатель степени со всеми битами, установленными на 1, используется для идентификации этих чисел. . Поле дроби, установленное на 0, используется для идентификации бесконечности (положительной или отрицательной, что определяется знаком), а ненулевое поле дроби определяет значение NaN.

person yole    schedule 22.03.2016

Java использует плавающую точку IEEE 754.

Большинство чисел выражаются в формате знак-экспонента-мантисса, где мантисса имеет неявное начало 1.

Крайние значения поля экспоненты (все нули и все единицы) не используются как нормальные значения экспоненты. Вместо этого они используются для обозначения особых случаев.

Все нули в экспоненте feild используются для представления чисел (включая как положительный, так и отрицательный ноль), которые слишком малы для представления в нормальном формате.

Все единицы в экспоненте используются для обозначения специальных значений. Если все биты мантиссы равны нулю, то значение равно плюс или минус бесконечность (знак указывается битом знака). В противном случае значение NaN.

person plugwash    schedule 22.03.2016

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

Общее число имеет вид: 1.M * 2 ^ e.

(где M называется мантиссой, а e - экспонента в избытке-127)

С плавающей запятой

MSB (старший значащий бит) используется как знаковый бит, а номер бита от 23 до 31 используется для экспоненциального значения в форме избытка-127, а номер бита от 0 до 30 используется для хранения мантиссы.

В двойном формате

MSB (старший значащий бит) используется как знаковый бит, а номер бита от 52 до 63 используется для экспоненциального значения в форме избыточного 127, а номер бита от 0 до используется для хранения мантиссы.

так что теперь мы можем понять представление NaN, Infinity в float или double.

NaN (не число)

В представлении NaN все биты экспоненты равны 1, а биты Мантиссы могут быть любыми, и не имеет значения, является ли это число с плавающей запятой или десятичным.

Бесконечность

В представлении Бесконечности все биты экспоненты равны 1, а биты Мантиссы равны 0, и не имеет значения, является ли это число с плавающей запятой или десятичное. положительная бесконечность представлена ​​таким же образом, как указано выше, но бит знака равен 0, а отрицательная бесконечность также представлена ​​тем же самым, но бит знака здесь равен 1.

person Rahul Dhawan    schedule 15.02.2017