наибольшее целое число, которое может быть сохранено в двойном - PullRequest
200 голосов
/ 04 декабря 2009

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

Ответы [ 7 ]

460 голосов
/ 04 декабря 2009

Наибольшее / наибольшее целое число, которое может быть сохранено в двойном значении без потери точности, равно максимально возможному значению двойного. То есть 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.

68 голосов
/ 04 декабря 2009

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
25 голосов
/ 04 декабря 2009

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

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

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

13 голосов
/ 30 сентября 2016

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

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

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

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

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

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

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

8 голосов
/ 04 декабря 2009

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

6 голосов
/ 04 декабря 2009
1 голос
/ 04 декабря 2009

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

...