Quando la conversione da Integer a Single può perdere precisione


27

Stavo leggendo un articolo di Microsoft su Ampliamento delle conversioni e Opzione rigorosa su quando sono arrivato alla parte

Le seguenti conversioni potrebbero perdere precisione:

  • Numero intero a Singolo
  • Lungo a singolo o doppio
  • Da decimale a singolo o doppio

Tuttavia, queste conversioni non perdono informazioni o grandezza.

.. ma secondo un altro articolo riguardante i tipi di dati ,

  • Il tipo intero può memorizzare da -2.147.483.648 a 2.147.483.647 e

  • Il tipo singolo può memorizzare da

    • 1.401298E-45 a 3,4028235E + 38 per numeri positivi,
    • e -3,4028235E da + 38 a - 1.401298E-45 per numeri negativi

.. così Single può memorizzare molti più numeri di Integer. Non riuscivo a capire in quale situazione tale conversione da Integer a Single potesse perdere precisione. Qualcuno potrebbe spiegare, per favore?

Risposte:


87

Single può memorizzare molti più numeri di Integer

No, non può. Entrambi Singlee Integersono 32 bit, il che significa che entrambi possono memorizzare esattamente lo stesso numero di numeri, ovvero 2 32 = 4294967296 numeri distinti.

Poiché l' intervallo di Singleè chiaramente maggiore di quello, è immediatamente ovvio (a causa del principio di Pigeonhole ) che non può rappresentare tutti i numeri all'interno di quell'intervallo.

E poiché l'intervallo di ha Integeresattamente le stesse dimensioni della quantità massima di numeri che entrambi Integere Singlepossono rappresentare, ma Singlepossono anche rappresentare numeri al di fuori di tale intervallo, è chiaro che non può rappresentare tutti i numeri all'interno dell'intervallo di Integer.

Se ci sono alcuni numeri Integerche non possono essere rappresentati Single, la conversione da Integerin Single deve essere in grado di perdere informazioni.


3
+1 per questa grande spiegazione del perché debba essere così, anche se la domanda era in realtà quando ("in quale situazione") succede ...
doubleYou

21
@doubleYou: 4261412864 dei 4294967296 Integers (99,2%) non possono essere rappresentati come Single, quindi "quando" è "praticamente sempre".
Jörg W Mittag,

2
Se vuoi essere più preciso, Singlepuò rappresentare solo 4.278.190.079 numeri diversi. Un Singlevalore rappresenta un numero se e solo se l'esponente memorizzato non è 255, il che significa che ci sono 255 * 2 ^ 24 Singles che rappresentano numeri. Di questi, due rappresentano lo stesso numero (vale a dire zero) e gli altri rappresentano numeri diversi.
Tanner Swett,

10
en.wikipedia.org/wiki/Single-precision_floating-point_format spiega bene le limitazioni per IEEE754 binary32. I numeri interi in [-16777216,16777216](2 ^ 24 = la larghezza del significato) possono essere rappresentati esattamente. I numeri più grandi sono arrotondati al multiplo più vicino di 2, 4, 8, ... a seconda di quanto sono grandi.
Peter Cordes,

14
“Il che significa che entrambi possono memorizzare la stessa quantità di numeri” - Non , non vuol dire che. Significherebbe solo che se entrambi i tipi hanno lo stesso numero esatto di modi per memorizzare ciascun numero. E questo non è il caso; per esempio, Singleha due modi per memorizzare zero. Quindi Singlepuò effettivamente rappresentare un numero minore di numeri distinti rispetto a Integer.
Konrad Rudolph,

28

I tipi a virgola mobile (come Single e Double) sono rappresentati in memoria da un segno, una mantissa e un esponente. Pensalo come una notazione scientifica:

Sign*Mantissa*Base^Exponent

Loro - come ci si può aspettare - usano la base 2. Ci sono altre modifiche che consentono di rappresentare l'infinito e il NaN, e l'esponente è sfalsato (tornerà a quello) e una scorciatoia per la mantissa (tornerà anche a quello) . Cerca lo standard IEEE 754 che copre la sua rappresentazione e le operazioni per maggiori dettagli.

Per i nostri scopi possiamo immaginarlo come un numero binario "mantissa" e un "esponente" che ti dice dove mettere il separatore decimale.


Nel caso di Single, abbiamo 1 bit per il suo segno, 8 per l'esponente e 23 per la mantissa.

Ora, il fatto è che memorizzeremo la mantissa dalla cifra più significativa. Ricorda che tutti gli zeri a sinistra non sono rilevanti. E dato che stiamo lavorando in binario, sappiamo che la cifra più significativa è 1 ※. Bene, poiché lo sappiamo, non è necessario memorizzarlo. Grazie a quella scorciatoia, l'intervallo effettivo della mantissa è di 24 bit.

※: A meno che il numero che stiamo memorizzando sia zero. Per questo avremo tutti i bit impostati su zero. Tuttavia, se proviamo a interpretare ciò sotto la descrizione che ho dato, avresti un 2 ^ 24 (l'implicito 1) moltiplicato per 1 (2 alla potenza dell'esponente 0). Quindi, per risolverlo, lo zero esponente è un valore speciale. Ci sono anche valori speciali per memorizzare l'infinito e NaN nell'esponente.

Secondo l'offset dell'esponente - oltre a evitare i valori speciali - il suo offset consente di posizionare il punto decimale prima dell'inizio della mantissa o dopo la sua fine, senza la necessità di avere un segno per l'esponente.


Ciò significa che per numeri grandi, il tipo a virgola mobile metterà il punto decimale oltre la fine della mantissa.

Ricorda che la mantissa è un numero di 24 bit. Non rappresenterà mai un numero di 25 bit ... non ha quel bit in più. Pertanto, il singolo non può distinguere tra 2 ^ 24 e 2 ^ 24 + 1 (questi sono i primi numeri di 25 bit e differiscono sull'ultimo bit, che non è rappresentato nel singolo).

Pertanto, per i numeri interi l'intervallo del singolo è compreso tra -2 ^ 24 e 2 ^ 24. E provare ad aggiungere da 1 a 2 ^ 24 si tradurrà in 2 ^ 24 (perché per quanto riguarda il tipo, 2 ^ 24 e 2 ^ 24 + 1 hanno lo stesso valore). Provalo online . Questo è il motivo per cui si verifica una perdita di informazioni durante la conversione da intero a singolo. Ed è anche per questo che un loop che utilizza un singolo o un doppio potrebbe effettivamente essere un loop infinito senza che te ne accorga.


Questa non è una spiegazione perfetta del 1bit iniziale implicito nel significato. È implicito nel fatto che il campo dell'esponente parziale è diverso da zero . I subnormali (noti anche come denormali) tra cui+-0.0 hanno una parte importante 0del loro significato. Immagino che potresti semplificare solo 0.0un caso del tutto speciale, ma in 0.0realtà segue le stesse regole di codifica di altri subnormali.
Peter Cordes,

25

Ecco un esempio reale di quando la conversione da Integerin Singlepuò perdere precisione:

Il Singletipo può memorizzare tutti i numeri interi da -16777216 a 16777216 (inclusi), ma non può memorizzare tutti i numeri al di fuori di questo intervallo. Ad esempio, non può memorizzare il numero 16777217. In tal caso, non può memorizzare alcun numero dispari maggiore di 16777216.

Possiamo usare Windows PowerShell per vedere cosa succede se convertiamo un Integerin Singlee viceversa:

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

Si noti che 16777217 è stato arrotondato per difetto a 16777216 e 16777219 è stato arrotondato per eccesso a 16777220.


4
E con intensità crescente, la distanza tra le floats rappresentabili più vicine continua a crescere come potenze di. en.wikipedia.org/wiki/…
Peter Cordes,

12

I tipi a virgola mobile sono simili alla "notazione scientifica" in fisica. Il numero è suddiviso in un bit di segno, un esponente (moltiplicatore) e una mantissa (cifre significative). Pertanto, all'aumentare della grandezza del valore aumenta anche la dimensione del passo.

La virgola mobile a precisione singola ha 23 bit di mantissa, ma esiste un "1 implicito", quindi la mantissa è effettivamente di 24 bit. Pertanto, tutti i numeri interi con magnitudo fino a 2 24 possono essere rappresentati esattamente in virgola mobile a precisione singola.

Inoltre, possono essere rappresentati un numero inferiore di numeri.

  • Da 2 24 a 2 25 possono essere rappresentati solo numeri pari.
  • Da 2 25 a 2 26 possono essere rappresentati solo multipli di 4.
  • Da 2 26 a 2 27 possono essere rappresentati solo multipli di 8.
  • Da 2 27 a 2 28 possono essere rappresentati solo multipli di 16
  • Da 2 28 a 2 29 possono essere rappresentati solo multipli di 32
  • Da 2 29 a 2 30 possono essere rappresentati solo multipli di 64
  • Da 2 30 a 2 31 possono essere rappresentati solo multipli di 128

Quindi dei 2 32 possibili valori interi con segno a 32 bit solo 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 possono essere rappresentati in virgola mobile a precisione singola. Questo è il 3.515625% del totale.


8

I galleggianti a precisione singola hanno 24 bit di precisione. Tutto ciò che viene arrotondato al numero a 24 bit più vicino. Potrebbe essere più facile da capire nella notazione scientifica decimale, ma tieni presente che i float effettivi usano il binario.

Supponi di avere 5 cifre decimali di memoria. Puoi scegliere di usare quelli come un normale int senza segno, che ti permette di avere qualsiasi numero tra 0 e 99999. Se vuoi essere in grado di rappresentare numeri più grandi, puoi usare la notazione scientifica e assegnare solo due cifre per essere l'esponente, quindi ora puoi rappresentare qualsiasi cosa tra 0 e 9.99 x 10 99 .

Tuttavia, il numero più grande che puoi rappresentare esattamente ora è solo 999. Se hai provato a rappresentare 12345, puoi ottenere 1,23 x 10 4 o 1,24 x 10 4 , ma non puoi rappresentare nessuno dei numeri in mezzo, perché non ci sono abbastanza cifre disponibili.


3
L'uso delle cifre decimali è una buona idea che rende più semplice la comprensione, ma l'ultimo paragrafo è un po 'fuorviante: in realtà puoi rappresentare numeri superiori a 999 e il tuo esempio lo mostra: 12300 sarebbe 1,23 x 10 <sup> 4 <sup >. Quello che vuoi dire è che a partire da quel numero ci sono degli spazi vuoti. Ti dispiacerebbe riformularlo un po '?
Fabio dice Reintegrare Monica il
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.