Какое наибольшее целое число без плавающих может быть сохранено в двойном типе IEEE 754 без потери точности?
Какое наибольшее целое число без плавающих может быть сохранено в двойном типе IEEE 754 без потери точности?
Ответы:
Наибольшее / наибольшее целое число, которое может храниться в двойном значении без потери точности, совпадает с наибольшим возможным значением двойного числа. То есть DBL_MAX
или примерно 1,8 × 10 308 (если ваш двойник является 64-битным двойником IEEE 754). Это целое число. Это представлено точно. Что вы еще хотите?
Продолжайте, спросите меня, какое наибольшее целое число такое, чтобы оно и все меньшие целые числа могли быть сохранены в 64-битных двойных числах IEEE без потери точности. 64-битный дубль IEEE имеет 52 бита мантиссы, поэтому я думаю, что это 2 53 :
Или другой способ взглянуть на это: как только смещение было снято с показателя степени, и игнорируя знаковый бит как не относящийся к вопросу, значение, хранимое в double, является степенью 2 плюс 52-битное целое число, умноженное на 2 показатель степени - 52 . Таким образом, с показателем 52 вы можете сохранить все значения от 2 52 до 2 53 - 1. Затем с показателем 53 следующее число, которое вы можете сохранить после 2 53, равно 2 53 + 1 × 2 53 - 52 . Таким образом, потеря точности сначала происходит с 2 53 + 1.
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
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
который дает тот же результат
while (dbl == --dbl)
будет цикл навсегда или нет вообще. :) (в данном случае совсем нет, так как это 2 ^ N). Вам придется подойти к нему снизу. Это также приведет к результату, который меньше ожидаемого (поскольку проверка в цикле while уменьшает dbl). И это зависит от порядка выполнения, если декремент выполняется до или после оценки левой стороны (насколько я знаю, неопределенна). Если это первое, оно всегда будет верным и зацикливается навсегда.
while (dbl + 1 != dbl) dbl++;
в том, что dbl + 1 != dbl
можно оценить с помощью long double
математики - рассмотрим FLT_EVAL_METHOD == 2
. Это может закончиться бесконечным циклом.
Википедия говорит об этом в том же контексте со ссылкой на IEEE 754 :
В типичной компьютерной системе двоичное число с плавающей запятой двойной точности (64-разрядное) имеет коэффициент 53 бита (один из которых подразумевается), показатель степени 11 бит и один знаковый бит.
2 ^ 53 составляет чуть более 9 * 10 ^ 15.
Наибольшее целое число, которое может быть представлено в двойном (64-разрядном) IEEE 754, совпадает с наибольшим значением, которое может представлять тип, поскольку само это целое число.
Это представляется как 0x7FEFFFFFFFFFFFFF
, который состоит из:
0x7FE
(2046, который представляет 1023 после смещения вычитается), а не 0x7FF
(2047, который указывает на NaN
или бесконечность).0xFFFFFFFFFFFFF
которая составляет 52 бита всего 1.В двоичном виде значение представляет собой неявную 1, за которой следуют еще 52 единицы из мантиссы, затем 971 ноль (1023 - 52 = 971) от показателя степени.
Точное десятичное значение:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
Это примерно 1,8 х 10 308 .
Вам нужно посмотреть на размер мантиссы. 64-битное число с плавающей запятой IEEE 754 (которое имеет 52 бита плюс 1 подразумевается) может точно представлять целые числа с абсолютным значением, меньшим или равным 2 ^ 53.
1.7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
от <float.h>
должен дать хотя бы разумное приближение этого. Поскольку это касается десятичных цифр и действительно хранится в двоичном формате, вы, вероятно, можете хранить что-то немного больше, не теряя точности, но сколько именно трудно сказать. Я полагаю, вы сможете понять это из FLT_RADIX
и DBL_MANT_DIG
, но я не уверен, что полностью доверю результату.
double
соответствует непосредственно определенному типу IEEE, но это не требуется, и когда этот ответ был написан, в вопросе также не упоминался конкретный тип IEEE.