Яке найбільше ціле число без плавання, яке можна зберігати в подвійному типі IEEE 754, не втрачаючи точності?
Яке найбільше ціле число без плавання, яке можна зберігати в подвійному типі IEEE 754, не втрачаючи точності?
Відповіді:
Найбільше / найбільше ціле число, яке можна зберегти у подвійному, не втрачаючи точності, те саме, що найбільше можливе значення подвійного. Тобто, DBL_MAX
або приблизно 1,8 × 10 308 (якщо ваш подвійний 64-розрядний IEEE 754). Це ціле число. Він представлений точно. Що ще ти хочеш?
Далі, запитайте мене, що таке найбільше ціле число, щоб воно та всі менші цілі числа могли зберігатися в 64-розрядних подвійних дублях IEEE, не втрачаючи точності. 64-розрядний подвійний IEEE має 52 біти мантіси, тому я думаю, що це 2 53 :
Або інший спосіб його погляду: як тільки зміщення було знято з показника, і ігнорування бітового знака як ірелевантного до питання, значення, яке зберігається у подвійному, - це потужність 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). Вам доведеться підходити до нього знизу. Це дійсно також призведе до меншого, ніж очікуваного (з моменту однієї перевірки зменшення циклу в той час, як 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, є таким самим, як найбільше значення, яке може представляти тип, оскільки саме це значення є цілим числом.
Це представлено як 0x7FEFFFFFFFFFFFFF
, що складається з:
0x7FE
(2046, що становить 1023 після віднімання зміщення), а не0x7FF
(2047, що вказує на a 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.