Qual è il primo numero intero che un float IEEE 754 non è in grado di rappresentare esattamente?


164

Per chiarezza, se sto usando un linguaggio che implementa IEE 754 float e dichiaro:

float f0 = 0.f;
float f1 = 1.f;

... e poi stampandoli indietro, riceverò 0,0000 e 1,0000 - esattamente.

Ma IEEE 754 non è in grado di rappresentare tutti i numeri lungo la linea reale. Vicino a zero, gli "spazi vuoti" sono piccoli; man mano che ci si allontana, le lacune si allargano.

Quindi, la mia domanda è: per un float IEEE 754, qual è il primo (più vicino a zero) intero che non può essere rappresentato esattamente? Per ora mi occupo solo dei float a 32 bit, anche se mi interesserà ascoltare la risposta a 64 bit se qualcuno lo dà!

Ho pensato che sarebbe semplice come calcolare 2 bits_of_mantissa e aggiungere 1, dove bits_of_mantissa è quanti bit espone lo standard. L'ho fatto per i float a 32 bit sulla mia macchina (MSVC ++, Win64) e, tuttavia, mi è sembrato perfetto.


Perché ne hai aggiunto uno se volevi un numero non rappresentabile? E quale numero hai usato o ottenuto? E questi sono i compiti? E il titolo della tua domanda dice "intero" ma la tua domanda dice "float".
msw

5
Perché ho pensato che il massimo della mantissa mi avrebbe dato il numero più alto rappresentabile. 2 ^ 22. No, è una domanda di curiosità. Mi sono sempre sentita in colpa nel mettere i float nei float, anche quando so che l'int in questione sarà sempre molto piccolo. Voglio sapere qual è il limite superiore. Per quanto posso dire, il titolo e la domanda sono gli stessi, solo formulati diversamente.
Floomi,



1
@KyleStrand ripristinato ^ 2. Non so perché uno mi sembrasse più corretto dell'altro in quel momento. Ora sembrano entrambi imbarazzanti rispetto a "... è il numero di bit ..."
Pascal Cuoq,

Risposte:


211

2 punte di mantissa + 1 + 1

Il +1 nell'esponente (bit di mantissa + 1) è perché, se la mantissa contiene abcdef...il numero che rappresenta è effettivamente 1.abcdef... × 2^e, fornisce un ulteriore bit implicito di precisione.

Pertanto, il primo numero intero che non può essere rappresentato con precisione e sarà arrotondato è:
Per float, 16.777.217 (2 24 + 1).
Per double, 9.007.199.254.740.993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992

Ho dichiarato a floate l' ho impostato pari a 16.777.217. Ma quando l'ho stampato usando coutne sono risultate 16.777.216. Sto usando C++. Perché non riesco a ottenere 16.777.217?
nitrato di sodio

18
@sodiumnitrate Controlla il titolo della domanda. 16777217 è il primo numero intero incapace di essere rappresentato esattamente.
kennytm,

Ok grazie. Mi sono confuso, mi dispiace per quello. Ho un'altra domanda però: dopo il 16777216, il prossimo numero intero che è rappresentabile non dovrebbe essere 2 * 16777216? Quando eseguo un programma simile, ottengo 16777218 aggiungendo 2 a 16777126.
nitrato di sodio

5
Il numero intero successivo è effettivamente 16777218, perché 2 ora diventa l'ultima cifra binaria significativa.
kennytm,

6
In C ++, cioè (1 << std::numeric_limits<float>::digits) + 1, e in C (1 << FLT_MANT_DIG) + 1,. Il primo è carino perché può far parte di un modello. Non aggiungere il +1 se vuoi solo il numero intero rappresentabile più grande.
Henry Schreiner,

38

Il valore più grande rappresentabile da un numero intero n bit è 2 n -1. Come notato sopra, a floatha 24 bit di precisione nel significato che sembrerebbe implicare che 2 24 non si adatterebbe.

Tuttavia .

I poteri di 2 all'interno dell'intervallo dell'esponente sono esattamente rappresentabili come 1,0 × 2 n , quindi 2 24 possono adattarsi e di conseguenza il primo numero intero non rappresentabile floatè 2 24 +1. Come sopra annotato. Ancora.


1
Ciò spiegava chiaramente la parte "di precisione extra implicita" dell'altra. Grazie.
Chappjc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.