наибольшее целое число, которое может быть сохранено в двойном

225

Какое наибольшее целое число без плавающих может быть сохранено в двойном типе IEEE 754 без потери точности?

Франк Фрайбургер
источник

Ответы:

506

Наибольшее / наибольшее целое число, которое может храниться в двойном значении без потери точности, совпадает с наибольшим возможным значением двойного числа. То есть DBL_MAXили примерно 1,8 × 10 308 (если ваш двойник является 64-битным двойником IEEE 754). Это целое число. Это представлено точно. Что вы еще хотите?

Продолжайте, спросите меня, какое наибольшее целое число такое, чтобы оно и все меньшие целые числа могли быть сохранены в 64-битных двойных числах IEEE без потери точности. 64-битный дубль IEEE имеет 52 бита мантиссы, поэтому я думаю, что это 2 53 :

  • 2 53 + 1 не может быть сохранено, потому что 1 в начале и 1 в конце имеют слишком много нулей между ними.
  • Все, что меньше 2 53 может быть сохранено, с 52 битами, которые явно хранятся в мантиссе, а затем экспонента дает вам еще один.
  • 2 53, очевидно, могут быть сохранены, так как это небольшая степень 2.

Или другой способ взглянуть на это: как только смещение было снято с показателя степени, и игнорируя знаковый бит как не относящийся к вопросу, значение, хранимое в double, является степенью 2 плюс 52-битное целое число, умноженное на 2 показатель степени - 52 . Таким образом, с показателем 52 вы можете сохранить все значения от 2 52 до 2 53  - 1. Затем с показателем 53 следующее число, которое вы можете сохранить после 2 53, равно 2 53 + 1 × 2 53 - 52 . Таким образом, потеря точности сначала происходит с 2 53 + 1.

Стив Джессоп
источник
126
+1 Хорошая работа, заметив, что вопрос на самом деле не означал того, что, вероятно, имел в виду спрашивающий, и предоставив оба ответа («технически правильный» и «вероятно ожидаемый»).
Паскаль Куок
62
Или «баловаться» и «пытаться помочь», как я их называю :-)
Стив Джессоп
8
Я кланяюсь Тони Пони, и никому другому.
Стив Джессоп
11
Вы не имеете в виду «все меньшие целые числа», вы подразумеваете все целые числа равной или меньшей величины. Потому что ниже 2 ^ 53 ниже много целых отрицательных чисел, и они не могут быть представлены в точности как двойные.
Южное гостеприимство
13
Я имею в виду меньше, и это именно то, что я имею в виду, когда я говорю меньше :-) -1 000 000 меньше 1, но не меньше.
Стив Джессоп
77

9007199254740992 (это 9 007 199 254 740 992) без каких-либо гарантий :)

программа

#include <math.h>
#include <stdio.h>

int main(void) {
  double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
  while (dbl + 1 != dbl) dbl++;
  printf("%.0f\n", dbl - 1);
  printf("%.0f\n", dbl);
  printf("%.0f\n", dbl + 1);
  return 0;
}

результат

9007199254740991
9007199254740992
9007199254740992
PMG
источник
7
Предполагая, что это будет «близко», но меньше 2 ^ N, тогда более быстрый тест, double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);который дает тот же результат
Seph
4
@ Что за ...? Нет? while (dbl == --dbl)будет цикл навсегда или нет вообще. :) (в данном случае совсем нет, так как это 2 ^ N). Вам придется подойти к нему снизу. Это также приведет к результату, который меньше ожидаемого (поскольку проверка в цикле while уменьшает dbl). И это зависит от порядка выполнения, если декремент выполняется до или после оценки левой стороны (насколько я знаю, неопределенна). Если это первое, оно всегда будет верным и зацикливается навсегда.
Фальстро
10
Может быть, указать, что 2 ^ 53 = 9,007,199,254,740,992 где-то.
Ксонатрон,
1
С этим сложно поспорить! Хороший эксперимент
MattM
Слабость к использованию while (dbl + 1 != dbl) dbl++;в том, что dbl + 1 != dblможно оценить с помощью long doubleматематики - рассмотрим FLT_EVAL_METHOD == 2. Это может закончиться бесконечным циклом.
Chux - Восстановить Монику
25

Википедия говорит об этом в том же контексте со ссылкой на IEEE 754 :

В типичной компьютерной системе двоичное число с плавающей запятой двойной точности (64-разрядное) имеет коэффициент 53 бита (один из которых подразумевается), показатель степени 11 бит и один знаковый бит.

2 ^ 53 составляет чуть более 9 * 10 ^ 15.

Карл Смотриц
источник
@ Стив Джессоп более или менее, это действительно то, что я говорю. Я также сталкивался с аппаратными системами, которые не имеют FPU, который все еще должен быть IEEE-совместимым, так что "типичные системные" вещи действительно не помогают мне, если я вернусь сюда через 8 месяцев и мне нужна та же информация для мой 68K-микроконтроллер (при условии, что у него нет FPU ... я не могу вспомнить).
Сан Хасинто
14
@ Сан Хасинто - «Это бесполезно» - это слишком грубо. Ответ весьма полезен, но не так полезен, как если бы он содержал комментарий о том, что типичные компьютерные системы действительно используют представление IEEE 754.
Стивен С. Сталь
@ Стефен С. Сталь, на самом деле ты прав. По моему сценарию, возвращаясь к этому позже и ища IEEE max, невозможно сказать, что такое «типичная система», но в ответе, кроме этой жалобы, все еще есть смысл.
Сан Хасинто
20

Наибольшее целое число, которое может быть представлено в двойном (64-разрядном) IEEE 754, совпадает с наибольшим значением, которое может представлять тип, поскольку само это целое число.

Это представляется как 0x7FEFFFFFFFFFFFFF, который состоит из:

  • Знаковый бит 0 (положительный), а не 1 (отрицательный)
  • Максимальный показатель 0x7FE(2046, который представляет 1023 после смещения вычитается), а не 0x7FF(2047, который указывает на NaNили бесконечность).
  • Максимальная мантисса, 0xFFFFFFFFFFFFFкоторая составляет 52 бита всего 1.

В двоичном виде значение представляет собой неявную 1, за которой следуют еще 52 единицы из мантиссы, затем 971 ноль (1023 - 52 = 971) от показателя степени.

Точное десятичное значение:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

Это примерно 1,8 х 10 308 .

Саймон Бибер
источник
Как насчет наибольшего значения, которое оно может представлять со всеми значениями между ним и непрерывно представляемым нулем?
Аарон Франке
@AaronFranke Вопрос не задавался о непрерывном представлении, но ответ на этот другой вопрос был включен в большинство других ответов здесь, или даже ошибочно дан как фактический ответ. Это 2⁵³ (2 к степени 53).
Саймон Бибер
8

Вам нужно посмотреть на размер мантиссы. 64-битное число с плавающей запятой IEEE 754 (которое имеет 52 бита плюс 1 подразумевается) может точно представлять целые числа с абсолютным значением, меньшим или равным 2 ^ 53.

дельфин
источник
8
Это может точно представлять 2 ^ 53, также :-)
Стив Джессоп
6

1.7976931348623157 × 10 ^ 308

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

сойка
источник
2
этот ответ был бы намного лучше с цитатой.
Сан Хасинто
2
@ Хорошо, если целое число имеет нули за пределами слева, то оно точно сохраняется.
Вильгельм
4
@all down downters: 1.7976931348623157 × 10 ^ 308 - точное целое число. Вам всем нужно посещать занятия по математике или что-то в этом роде?
Дэн Молдинг
6
При обсуждении этого безнадежно утонувшего ответа мы дошли до семантики. Правда, это число может быть представлено точно и тем самым соответствует букве вопроса. Но мы все знаем, что это крошечный островок точности в океане промахов, и большинство из нас правильно интерпретировали вопрос, чтобы обозначить «наибольшее число, за пределы которого точность падает в канализацию». Ах, разве не удивительно, что CompSci - точная наука? :)
Карл Смотриц
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 - точное целое число, но я уверен, что это конкретное целое не может быть сохранено точно в двойном.
Паскаль Куок
2

DECIMAL_DIGот <float.h>должен дать хотя бы разумное приближение этого. Поскольку это касается десятичных цифр и действительно хранится в двоичном формате, вы, вероятно, можете хранить что-то немного больше, не теряя точности, но сколько именно трудно сказать. Я полагаю, вы сможете понять это из FLT_RADIXи DBL_MANT_DIG, но я не уверен, что полностью доверю результату.

Джерри Гроб
источник
Это не дает ответа на вопрос. Чтобы критиковать или запросить разъяснения у автора, оставьте комментарий под своим постом.
MichaelChirico
@MichaelChirico: Это отвечает на вопрос, который он намеревался задать, поскольку он существовал, когда был написан ответ. Чтобы просмотреть историю изменений вопроса, нажмите ссылку «отредактировано 19 июня '14 в 11:40» в нижней части вопроса.
Джерри Гроб
ваш ответ читается как комментарий, потому что кажется, что ему не хватает уверенности / авторитетности, который должен иметь ответ («должен дать хотя бы разумный ...», «сколько именно ... трудно сказать» «я полагаю ...» ") У меня нет опыта по заданному вопросу или ответу, поэтому я могу ошибаться; просто вставив мои два цента, учитывая, что меня отправили сюда из очереди на проверку (что, я думаю, означает, что другие пользователи отметили ваш ответ).
MichaelChirico
1
@MichaelChirico: Они вполне могут иметь - вы далеко не единственный, кто не знает предмета; Что делает тебя необычным, так это то, что ты понимаешь, что не знаешь об этом. Большинство ответов, которые звучат авторитетно относительно точности числа с плавающей запятой в C, просто ошибочны. Например, многие (большинство) из них выше основаны на ложном предположении, что a doubleсоответствует непосредственно определенному типу IEEE, но это не требуется, и когда этот ответ был написан, в вопросе также не упоминался конкретный тип IEEE.
Джерри Гроб
понял. Возможно, я бы предложил добавить эту информацию в ответ.
MichaelChirico