Qual è il più grande numero intero "no-floating" che può essere memorizzato in un doppio tipo IEEE 754 senza perdere precisione?
Qual è il più grande numero intero "no-floating" che può essere memorizzato in un doppio tipo IEEE 754 senza perdere precisione?
Risposte:
L'intero più grande / più grande che può essere memorizzato in un doppio senza perdere precisione è lo stesso del valore più grande possibile di un doppio. Cioè, DBL_MAX
o circa 1,8 × 10 308 (se il doppio è un doppio IEEE 754 a 64 bit). È un numero intero. È rappresentato esattamente. Che cosa vuoi di più?
Dai, chiedimi qual è il numero intero più grande, in modo tale che esso e tutti i numeri più piccoli possano essere memorizzati in IEEE a 64 bit doppi senza perdere precisione. Un doppio IEEE a 64 bit ha 52 bit di mantissa, quindi penso che sia 2 53 :
O un altro modo di vederlo: una volta che il bias è stato rimosso dall'esponente e ignorato il bit del segno come irrilevante per la domanda, il valore memorizzato da un doppio è una potenza di 2, più un intero di 52 bit moltiplicato per 2 esponente - 52 . Quindi con l'esponente 52 è possibile memorizzare tutti i valori da 2 52 a 2 53 - 1. Quindi con l'esponente 53, il numero successivo che è possibile memorizzare dopo 2 53 è 2 53 + 1 × 2 53 - 52 . Quindi la perdita di precisione si verifica prima con 2 53 + 1.
9007199254740992 (sono 9.007.199.254.740.992) senza garanzie :)
Programma
#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;
}
Risultato
9007199254740991 9007199254740992 9007199254740992
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
che produce lo stesso risultato
while (dbl == --dbl)
eseguirà il loop per sempre o per niente. :) (in questo caso, per niente, dato che è un 2 ^ N). Dovrai avvicinarti dal basso. Ne risulterà sicuramente anche uno in meno del risultato previsto (dal momento che quello verifica nel ciclo while diminuisce dbl). E dipende dall'ordine di esecuzione, se il decremento viene eseguito prima o dopo aver valutato il lato sinistro (che non è definito per quanto ne so). Se è il primo, sarà sempre vero e continuerà per sempre.
while (dbl + 1 != dbl) dbl++;
che dbl + 1 != dbl
può valutare l'utilizzolong double
matematica - considera FLT_EVAL_METHOD == 2
. Questo potrebbe finire in un ciclo infinito.
Wikipedia ha questo da dire nello stesso contesto con un link a IEEE 754 :
Su un tipico sistema informatico, un numero in virgola mobile binario a "doppia precisione" (64 bit) ha un coefficiente di 53 bit (di cui uno implicito), un esponente di 11 bit e un bit di segno.
2 ^ 53 è poco più di 9 * 10 ^ 15.
Il numero intero più grande che può essere rappresentato in IEEE 754 double (64-bit) è uguale al valore più grande che il tipo può rappresentare, poiché quel valore è esso stesso un numero intero.
Questo è rappresentato come 0x7FEFFFFFFFFFFFFF
, che è composto da:
0x7FE
(2046 che rappresenta 1023 dopo la sottrazione del bias) anziché 0x7FF
(2047 che indica a NaN
o infinito).0xFFFFFFFFFFFFF
che è 52 bit tutti 1.In binario, il valore è 1 implicito seguito da altri 52 dalla mantissa, quindi 971 zeri (1023 - 52 = 971) dall'esponente.
Il valore decimale esatto è:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
Si tratta di circa 1,8 x 10 308 .
Devi guardare le dimensioni della mantissa. Un numero in virgola mobile IEEE 754 a 64 bit (che ha 52 bit, più 1 implicito) può rappresentare esattamente numeri interi con un valore assoluto inferiore o uguale a 2 ^ 53.
1.7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
da <float.h>
dovrebbe fornire almeno una ragionevole approssimazione di ciò. Dal momento che si occupa di cifre decimali ed è davvero memorizzato in binario, probabilmente puoi memorizzare qualcosa di un po ' più grande senza perdere precisione, ma esattamente quanto è difficile da dire. Suppongo che dovresti essere in grado di capirlo da FLT_RADIX
e DBL_MANT_DIG
, ma non sono sicuro che mi fiderei completamente del risultato.
double
corrisponda direttamente a uno specifico tipo IEEE, ma ciò non è necessario e quando questa risposta è stata scritta la domanda non menzionava nemmeno un particolare tipo IEEE.