Quando usi float e quando usi double


194

Spesso nella mia esperienza di programmazione devo decidere se usare float o double per i miei numeri reali. A volte vado per il float, a volte vado per il doppio, ma in realtà questo sembra più soggettivo. Se dovessi confrontarmi per difendere la mia decisione, probabilmente non darei ragioni valide.

Quando usi il float e quando usi il double? Usi sempre il doppio, solo quando sono presenti vincoli di memoria vai per float? Oppure usi sempre il float a meno che il requisito di precisione non richieda il doppio? Ci sono alcune differenze sostanziali riguardo alla complessità computazionale degli aritemici di base tra float e double? Quali sono i pro e i contro dell'utilizzo di float o double? E hai mai usato il doppio lungo?


28
In molti casi non si desidera utilizzare nessuno dei due, ma piuttosto un tipo decimale mobile o fisso. I tipi binari a virgola mobile non possono rappresentare esattamente la maggior parte dei decimali.
CodesInChaos,

3
Relativo a Che cosa causa gli errori di arrotondamento in virgola mobile? . @CodesInChaos la mia risposta suggerisce delle risorse per aiutarti a prendere quella decisione, non esiste una soluzione unica per tutti .
Mark Booth,

Ottima risposta trovata a: Stack Overflow
Haris,

5
Cosa intendi esattamente con "decimali". Se devi rappresentare esattamente valori come 0,01 (diciamo, per soldi), la virgola mobile (binaria) non è la risposta. Se intendi semplicemente numeri non interi, allora il virgola mobile è probabilmente ok - ma quindi "decimali" non è la parola migliore per descrivere ciò di cui hai bisogno.
Keith Thompson,

1
Non hai sempre scelta. Ad esempio, sulla piattaforma Arduino, sia double che float equivalgono a float. È necessario trovare una libreria di componenti aggiuntivi per gestire i doppi reali.
kiwiron,

Risposte:


187

La scelta predefinita per un tipo a virgola mobile dovrebbe essere double. Questo è anche il tipo che si ottiene con valori letterali in virgola mobile senza suffisso o (in C) funzioni standard che operano su numeri in virgola mobile (ad es exp. sin, Ecc.).

float dovrebbe essere usato solo se è necessario operare su molti numeri in virgola mobile (pensare nell'ordine di migliaia o più) e l'analisi dell'algoritmo ha dimostrato che l'intervallo e la precisione ridotti non rappresentano un problema.

long doublepuò essere utilizzato se hai bisogno di più portata o precisione di double, e se lo fornisce sulla tua piattaforma di destinazione.

In sintesi, floate long doubledovrebbe essere riservato per l'uso da parte degli specialisti, con un doubleuso "quotidiano".


10
Probabilmente non prenderei in considerazione il float per alcune migliaia di valori a meno che non ci fosse un problema di prestazioni relativo alla memorizzazione nella cache in virgola mobile e al trasferimento dei dati. Di solito c'è un costo sostanziale per fare l'analisi per dimostrare che il float è abbastanza preciso.
Patricia Shanahan,

4
Come addendum, se è necessaria la compatibilità con altri sistemi, può essere vantaggioso utilizzare gli stessi tipi di dati.
zzzzBov,

15
Userei i float per milioni di numeri, non per 1000. Inoltre, alcune GPU funzionano meglio con i float, in quel caso specializzato usano float. Altrimenti, come dici tu, usa i doppi.
user949300,

4
@PatriciaShanahan - "problema di prestazioni correlato a .." Un buon esempio è se stai pianificando di utilizzare SSE2 o istruzioni vettoriali simili, puoi eseguire 4 operazioni / vettore in virgola mobile (vs 2 per doppio) che può dare un significativo miglioramento della velocità ( metà delle operazioni e metà della quantità di dati da leggere e scrivere). Ciò può abbassare significativamente la soglia in cui l'utilizzo dei float diventa attraente e vale la pena risolvere i problemi numerici.
Greggo,

12
Approvo questa risposta con un ulteriore consiglio: quando si opera con valori RGB per il display, è accettabile usare float(e occasionalmente metà precisione) perché né l'occhio umano, il display o il sistema di colore hanno così tanti bit di precisione . Questo consiglio è applicabile ad esempio OpenGL ecc. Questo consiglio aggiuntivo non si applica alle immagini mediche, che hanno requisiti di precisione più rigorosi.
rwong

42

Raramente c'è motivo di usare float invece di raddoppiare nel codice destinato ai computer moderni. La precisione aggiuntiva riduce (ma non elimina) la possibilità di errori di arrotondamento o altre imprecisioni che causano problemi.

I motivi principali che mi vengono in mente di usare float sono:

  1. Stai memorizzando grandi matrici di numeri e devi ridurre il consumo di memoria del tuo programma.
  2. Stai prendendo di mira un sistema che non supporta nativamente la virgola mobile a precisione doppia. Fino a poco tempo fa, molte schede grafiche supportavano solo punti mobili a precisione singola. Sono sicuro che ci sono molti processori embedded e di bassa potenza che hanno anche un supporto limitato in virgola mobile.
  3. Stai prendendo di mira l'hardware in cui la precisione singola è più veloce della doppia precisione e la tua applicazione fa un uso intensivo dell'aritmetica in virgola mobile. Sulle moderne CPU Intel credo che tutti i calcoli in virgola mobile vengano eseguiti in doppia precisione, quindi non si ottiene nulla qui.
  4. Stai eseguendo un'ottimizzazione di basso livello, ad esempio utilizzando istruzioni speciali della CPU che funzionano su più numeri contemporaneamente.

Quindi, in sostanza, il doppio è la strada da percorrere a meno che tu non abbia limiti hardware o a meno che l'analisi non abbia dimostrato che la memorizzazione di numeri a doppia precisione sta contribuendo in modo significativo all'utilizzo della memoria.


2
"Computer moderni" significa processori Intel x86. Alcune delle macchine utilizzate dagli Antichi fornivano una precisione perfettamente adeguata con il tipo a galleggiante di base. (Il CDC 6600 utilizzava una parola a 60 bit, 48 bit di mantissa a virgola mobile normalizzata, 12 bit di esponente. È QUASI quello che ti dà la x86 per una doppia precisione.)
John R. Strohm,

@ John.R.Strohm: d'accordo, ma i compilatori C non esistevano su CDC6600. Era Fortran IV ...
Basile Starynkevitch il

Per "computer moderni" intendo qualsiasi processore costruito nell'ultimo decennio o due, o davvero, poiché lo standard IEEE in virgola mobile è stato ampiamente implementato. Sono perfettamente consapevole dell'esistenza di architetture non x86 e ho pensato a ciò con la mia risposta: ho citato GPU e processori integrati, che in genere non sono x86.
user611910,

Questo non è semplicemente vero, però. SSE2 può manipolare 4 float o 2 doppi in una sola operazione, AVX può manipolare 8 float o 4 doppi, AVX-512 può manipolare 16 float o 8 doppi. Per qualsiasi tipo di calcolo ad alte prestazioni, la matematica sui float dovrebbe essere pensata come il doppio della velocità delle stesse operazioni sui doppi su x86.
Larry Gritz,

1
Ed è anche peggio, dal momento che puoi raddoppiare il doppio dei float nella cache del processore rispetto ai doppi, e la latenza di memoria è probabilmente il principale collo di bottiglia in molti programmi. Mantenere un intero set di float funzionante nella cache può essere letteralmente un ordine di grandezza più veloce rispetto all'utilizzo dei doppi e alla loro diffusione in RAM.
Larry Gritz,

10

Utilizzare doubleper tutti i calcoli e le variabili temporanee. Utilizzare floatquando è necessario mantenere una serie di numeri float[](se la precisione è sufficiente) e si ha a che fare con oltre decine di migliaia di floatnumeri.

Molte / la maggior parte delle funzioni matematiche o degli operatori convertono / restituiscono doublee non si desidera ricollegare i numeri floatper eventuali passaggi intermedi.

Ad esempio, se hai un input di 100.000 numeri da un file o da uno stream e devi ordinarli, inserisci i numeri in a float[].


5

Alcune piattaforme (ARM Cortex-M2, Cortex-M4 ecc.) Non supportano il doppio (può sempre essere verificato nel manuale di riferimento del processore. Se non ci sono avvisi o errori di compilazione, ciò non significa che il codice sia ottimale. il doppio può essere emulato.). Ecco perché potrebbe essere necessario attenersi a int o float .

Se così non fosse, userei il doppio .

Puoi controllare il famoso articolo di D. Goldberg ("Ciò che ogni scienziato informatico dovrebbe sapere sull'aritmetica a virgola mobile"). Dovresti pensarci due volte prima di usare l'aritmetica in virgola mobile. C'è una grande possibilità che non siano affatto necessari nella tua situazione particolare.

http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf


3
A questa domanda è già stata data una risposta abbastanza buona un anno fa ... ma in ogni caso, direi che ogni volta che stai usando il doppio su piattaforme con accelerazione FPU a doppia precisione, dovresti usarlo su qualsiasi altro, anche se ciò significa lasciando che il compilatore lo emuli invece di sfruttare una FPU con solo virgola mobile (si noti che nemmeno le FPU sono richieste su tutte le piattaforme, infatti un'architettura Cortex-M4 le definisce come una funzionalità opzionale [M2 era un errore di battitura?] ).
Selali Adobor,

La chiave di questa logica è, mentre è vero che uno dovrebbe essere stanco dell'aritmetica in virgola mobile, ed è molte "stranezze", sicuramente non prendere la presenza del supporto FPU per i doppi significa semplicemente usare doppi invece di float. I float sono generalmente più veloci dei doppi e occupano meno memoria (le funzionalità FPU variano). Il volume di utilizzo preclude a questo punto l'ottimizzazione prematura. Come il fatto, i doppi sono chiaramente eccessivi per molte (forse anche la maggior parte) applicazioni. Gli elementi di questa pagina hanno davvero bisogno che le loro posizioni e dimensioni relative siano calcolate con 13 cifre decimali?
Selali Adobor,

2
Quando si include un collegamento a una pagina o documento fuori sito, copiare le informazioni pertinenti o un riepilogo dal documento nella risposta. I collegamenti fuori sede tendono a scomparire nel tempo.
Adam Zuckerman,

3

Per i problemi del mondo reale, la soglia di campionamento dei dati è importante quando si risponde a questa domanda. Allo stesso modo, anche il rumore di fondo è importante. Se uno dei due viene superato dalla selezione del tipo di dati, nessun vantaggio verrà dalla crescente precisione.

La maggior parte dei campionatori del mondo reale sono limitati a DAC a 24 bit. Suggerendo che 32 bit di precisione sui calcoli del mondo reale dovrebbero essere adeguati dove il significato è di 24 bit di precisione.

La doppia precisione ha un costo di 2x memoria. Pertanto, limitare l'uso dei doppi sui float potrebbe ridurre drasticamente l'ingombro della memoria / larghezza di banda delle applicazioni in esecuzione.


-3

La scelta della variabile da utilizzare tra float e double dipende dalla precisione dei dati richiesti. Se una risposta deve avere una differenza trascurabile dalla risposta effettiva, il numero di posizioni decimali richiesto sarà molti, quindi detterà quel doppio da utilizzare.


3
Questa risposta non aggiunge nulla di nuovo alla domanda e non dice nulla di reale utilizzo.
Martijn Pieters,

-5

Di solito, uso il floattipo quando non ho bisogno di molta precisione, ad esempio per soldi, il che è sbagliato, ma è ciò a cui sono abituato.

D'altro canto, utilizzo doublequando ho bisogno di maggiore precisione, ad esempio per algoritmi matematici complessi.

Lo standard C99 dice questo:

Esistono tre tipi di virgola mobile: float, double e long double. Il tipo double offre almeno la stessa precisione del float e il tipo long double fornisce almeno la stessa precisione del double. L'insieme di valori del tipo float è un sottoinsieme dell'insieme di valori del tipo double; l'insieme di valori del tipo double è un sottoinsieme dell'insieme di valori del tipo long double.

Non l'ho mai usato davvero long double, ma non uso C / C ++ così tanto. Di solito uso linguaggi tipicamente dinamici come Python, in cui non devi preoccuparti dei tipi.

Per ulteriori informazioni su Double vs Float , vedere questa domanda in SO .


25
L'uso di virgola mobile per calcoli con denaro serio è probabilmente un errore.
Bart van Ingen Schenau,

17
float è esattamente il tipo sbagliato per soldi. Devi usare la massima precisione possibile.
ChrisF

8
@BartvanIngenSchenau Il virgola mobile per denaro di solito va bene, il virgola mobile binario no. Ad esempio .net Decimalè un tipo a virgola mobile ed è in genere una buona scelta per i calcoli del denaro.
CodesInChaos,

13
@ChrisF Non hai bisogno di "alta precisione" per soldi, hai bisogno di valori esatti.
Sean McSomething,

2
@SeanMcSomething - Fair point. Tuttavia, i float sono comunque del tipo sbagliato e dati i tipi in virgola mobile disponibili nella maggior parte delle lingue è necessaria "alta precisione" per ottenere "valori esatti".
ChrisF
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.