precisione 'float' vs. 'double'


155

Il codice

float x  = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);

ti darà l'output

x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116

dove sulla terza riga di output 741012573242è immondizia e sulla quarta riga 116è immondizia. I doppi hanno sempre 16 cifre significative mentre i float hanno sempre 7 cifre significative? Perché i doppi non hanno 14 cifre significative?

Risposte:


146

I numeri in virgola mobile in C usano la codifica IEEE 754 .

Questo tipo di codifica utilizza un segno, un significato e un esponente.

A causa di questa codifica, molti numeri avranno piccole modifiche per consentirne la memorizzazione.

Inoltre, il numero di cifre significative può cambiare leggermente poiché è una rappresentazione binaria, non decimale.

La precisione singola (float) fornisce 23 bit di significato, 8 bit di esponente e 1 bit di segno.

La doppia precisione (doppia) fornisce 52 bit di significato, 11 bit di esponente e 1 bit di segno.


4
C99 lo fa, prima dipendeva dal compilatore.
Alan Geleynse,

21
-1 Questa affermazione è palesemente falsa: "A causa di questa codifica, non puoi mai garantire che non cambierai il tuo valore."
R .. GitHub smette di aiutare ICE il

16
@Alan: C99 non richiede IEEE in virgola mobile; lo raccomanda e basta.
R .. GitHub smette di aiutare ICE il

4
@Alan: R .. è corretto; L'allegato F (che specifica i collegamenti IEEE-754) è normativo, ma ha effetto solo se viene definita un'implementazione __STDC_IEC_559__. Un'implementazione che non definisce che la macro è libera non conforme a IEEE-754.
Stephen Canon,

12
@Alan: Sotto IEEE 754, è facilmente garantito che non v'è alcun cambiamento nei valori 0.5, 0.046875o 0.376739501953125contro le loro rappresentazioni decimali. (Questi sono tutti razionali diadica con raccordo numeratore nella mantissa e logaritmo a base 2 del denominatore in raccordo l'esponente.)
R .. GitHub smettere di aiutare ICE

42

I doppi hanno sempre 16 cifre significative mentre i float hanno sempre 7 cifre significative?

No. I doppi hanno sempre 53 bit significativi e i float hanno sempre 24 bit significativi (ad eccezione dei valori denormali, infiniti e NaN, ma quelli sono soggetti per una domanda diversa). Questi sono formati binari e puoi solo parlare chiaramente della precisione delle loro rappresentazioni in termini di cifre binarie (bit).

Questo è analogo alla domanda su quante cifre possono essere memorizzate in un numero intero binario: un numero intero a 32 bit senza segno può memorizzare numeri interi con un massimo di 32 bit, che non si associa esattamente a nessun numero di cifre decimali: tutti i numeri interi fino a È possibile memorizzare 9 cifre decimali, ma è possibile memorizzare anche molti numeri di 10 cifre.

Perché i doppi non hanno 14 cifre significative?

La codifica di un doppio utilizza 64 bit (1 bit per il segno, 11 bit per l'esponente, 52 bit significativi espliciti e un bit implicito), che è il doppio del numero di bit utilizzati per rappresentare un float (32 bit).


15

float: 23 bit di significando, 8 bit di esponente e 1 bit di segno.

double: 52 bit di significando, 11 bit di esponente e 1 bit di segno.


11

Di solito si basa su cifre significative sia dell'esponente che del significato nella base 2, non nella base 10. Da quanto posso dire nello standard C99, tuttavia, non esiste una precisione specificata per float e double (a parte il fatto che 1 e 1 + 1E-5/ 1 + 1E-7sono distinguibili [ floate doubleripetutamente]). Tuttavia, il numero di cifre significative è lasciato all'implementatore (così come la base che usano internamente, quindi in altre parole un'implementazione potrebbe decidere di farcela sulla base di 18 cifre di precisione nella base 3). [1]

Se è necessario conoscere questi valori, le costanti FLT_RADIXe FLT_MANT_DIG(e DBL_MANT_DIG/ LDBL_MANT_DIG) sono definite in float.h.

Il motivo per cui si chiama a doubleè perché il numero di byte utilizzati per memorizzarlo è il doppio del numero di un float (ma questo include sia l'esponente che il significato). Lo standard IEEE 754 (utilizzato dalla maggior parte dei compilatori) alloca relativamente più bit per il significato dell'esponente (da 23 a 9 floatcontro 52 a 12 per double), motivo per cui la precisione è più che raddoppiata.

1: Sezione 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )


Errore di battitura? C89 richiede al massimo un epsilon 1E-9per double, no 1E-7.
Rufflewind,


4

Non è esattamente doppia precisione a causa di come funziona IEEE 754 e perché il binario non si traduce realmente in decimale. Dai un'occhiata allo standard se sei interessato.


4

float indica il numero in virgola mobile. In C, il tipo di dati float viene utilizzato nei casi in cui la precisione del numero totale di cifre è 7.Per esempio: - il numero decimale. 12.3546987 non può essere memorizzato in float perché ha un totale di 9 cifre. L'output verrà visualizzato come 12.354699, ovvero le prime 7 cifre verranno visualizzate come immesse nell'input e l'ottava cifra verrà arrotondata. Il tipo float può rappresentare valori che vanno da circa 1,5 x 10 ^ (- 45) a 3,4 x 10 ^ (38). In termini di allocazione della memoria, float è un tipo di dati a virgola mobile a precisione singola a 32 bit.

A differenza di float, double ha una precisione da 15 a 16 cifre. L'intervallo di double è da 5,0 × 10 ^ (- 345) a 1,7 × 10 ^ (308). In termini di allocazione dei byte, double è un dato in virgola mobile a 64 bit genere.

Il problema sorge nel suo utilizzo. Float o double non influisce su printf ma in caso di scanf si deve usare il tipo di dati appropriato a seconda del totale no. di cifre in n. che deve essere letto dall'input.

Quindi il doppio è preferito al float per una maggiore precisione dei dati.

Spero che questo ti aiuti.

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.