Quali sono i vantaggi e gli svantaggi dell'utilizzo di uno invece dell'altro in C ++?
Quali sono i vantaggi e gli svantaggi dell'utilizzo di uno invece dell'altro in C ++?
Risposte:
Se vuoi conoscere la vera risposta, dovresti leggere Quello che ogni informatico dovrebbe sapere sull'aritmetica a virgola mobile .
In breve, sebbene double
consenta una maggiore precisione nella sua rappresentazione, per alcuni calcoli produrrebbe errori maggiori . La scelta "giusta" è: usa tutta la precisione che ti serve ma non di più e scegli l'algoritmo giusto .
Molti compilatori eseguono calcoli in virgola mobile estesi in modalità "non rigorosa" comunque (cioè usano un tipo di virgola mobile più ampio disponibile nell'hardware, ad esempio 80 bit e 128 bit mobili), anche questo dovrebbe essere preso in considerazione. In pratica, difficilmente puoi vedere alcuna differenza di velocità : sono comunque nativi dell'hardware.
double
: è più sicuro nella maggior parte dei casi.
A meno che tu non abbia una ragione specifica per fare diversamente, usa double.
Forse sorprendentemente, è double e non float che è il tipo a virgola mobile "normale" in C (e C ++). Le funzioni matematiche standard come sin e log accettano i doppi come argomenti e restituiscono i doppi. Un normale letterale a virgola mobile, come quando scrivi 3.14 nel tuo programma, ha il tipo double. Non galleggiare.
Sui tipici computer moderni, i doppi possono essere veloci quanto i float, o anche più veloci, quindi le prestazioni di solito non sono un fattore da considerare, anche per calcoli di grandi dimensioni. (E quelli dovrebbero essere calcoli di grandi dimensioni , o le prestazioni non dovrebbero nemmeno entrare nella tua mente. Il mio nuovo computer desktop i7 può eseguire sei miliardi di moltiplicazioni di doppi in un secondo.)
È impossibile rispondere a questa domanda poiché non esiste un contesto per la domanda. Ecco alcune cose che possono influenzare la scelta:
Implementazione del compilatore di float, double e double long. Lo standard C ++ afferma:
Esistono tre tipi di virgola mobile: float, double e long double. Il tipo double fornisce almeno la stessa precisione del float e il tipo long double fornisce almeno la stessa precisione del double.
Quindi, tutti e tre possono avere la stessa dimensione in memoria.
Presenza di una FPU. Non tutte le CPU hanno FPU e talvolta i tipi a virgola mobile vengono emulati e talvolta i tipi a virgola mobile non sono supportati.
Architettura FPU. L'FPU dell'IA32 è a 80 bit internamente: i float a 32 bit e 64 bit vengono espansi a 80 bit al caricamento e ridotti in negozio. C'è anche SIMD che può eseguire quattro float a 32 bit o due float a 64 bit in parallelo. L'uso di SIMD non è definito nello standard, quindi richiederebbe un compilatore che esegue analisi più complesse per determinare se SIMD può essere utilizzato, o richiede l'uso di funzioni speciali (librerie o intrinseche). Il risultato del formato interno a 80 bit è che puoi ottenere risultati leggermente diversi a seconda della frequenza con cui i dati vengono salvati nella RAM (quindi, perdendo precisione). Per questo motivo, i compilatori non ottimizzano particolarmente bene il codice in virgola mobile.
Banda di memoria. Se un double richiede più spazio di archiviazione di un float, ci vorrà più tempo per leggere i dati. Questa è la risposta ingenua. Su un moderno IA32, tutto dipende da dove provengono i dati. Se è nella cache L1, il carico è trascurabile a condizione che i dati provengano da una singola riga della cache. Se si estende su più di una riga della cache, si verifica un piccolo overhead. Se è di L2, ci vuole un po 'di più, se è nella RAM, è ancora più lungo e, infine, se è su disco è un tempo enorme. Quindi la scelta di float o double è meno importante del modo in cui vengono utilizzati i dati. Se si desidera eseguire un piccolo calcolo su molti dati sequenziali, è preferibile un tipo di dati piccolo. Fare molti calcoli su un piccolo set di dati consentirebbe di utilizzare tipi di dati più grandi con effetti significativi. Se tu' accedendo ai dati in modo molto casuale, la scelta della dimensione dei dati non è importante: i dati vengono caricati nelle pagine / righe della cache. Quindi, anche se vuoi solo un byte dalla RAM, potresti ottenere 32 byte trasferiti (questo dipende molto dall'architettura del sistema). Oltre a tutto ciò, la CPU / FPU potrebbe essere super scalare (ovvero pipeline). Quindi, anche se un carico può richiedere diversi cicli, la CPU / FPU potrebbe essere impegnata a fare qualcos'altro (un moltiplicatore per esempio) che nasconde il tempo di caricamento in una certa misura.
Lo standard non impone alcun formato particolare per i valori in virgola mobile.
Se disponi di una specifica, questa ti guiderà alla scelta ottimale. Altrimenti, dipende dall'esperienza su cosa usare.
Double è più preciso ma è codificato su 8 byte. float è di soli 4 byte, quindi meno spazio e meno precisione.
Dovresti stare molto attento se hai double e float nella tua applicazione. Ho avuto un bug a causa di questo in passato. Una parte del codice utilizzava float mentre il resto del codice utilizzava double. Copiare double in float e poi float in double può causare un errore di precisione che può avere un grande impatto. Nel mio caso, era una fabbrica chimica ... si spera che non abbia avuto conseguenze drammatiche :)
Penso che sia a causa di questo tipo di bug che il razzo Ariane 6 è esploso qualche anno fa !!!
Pensa attentamente al tipo da utilizzare per una variabile
Questo dipende da come il compilatore implementa double. È legale che double e float siano dello stesso tipo (ed è su alcuni sistemi).
Detto questo, se sono davvero diversi, il problema principale è la precisione. Un doppio ha una precisione molto maggiore a causa della sua differenza di dimensioni. Se i numeri che stai usando normalmente superano il valore di un float, usa un double.
Diverse altre persone hanno menzionato problemi di performance. Sarebbe esattamente l'ultimo della mia lista di considerazioni. La correttezza dovrebbe essere la tua considerazione n. 1.
Utilizzare la precisione richiesta per ottenere i risultati appropriati . Se poi trovi che il tuo codice non funziona come vorresti (hai usato la profilazione corretta?) Dai un'occhiata a:
Penso che indipendentemente dalle differenze (che come tutti sottolineano, i galleggianti occupano meno spazio e sono in generale più veloci) ... qualcuno ha mai avuto problemi di prestazioni usando il doppio? Dico usa il doppio ... e se in seguito decidi "wow, questo è davvero lento" ... trova il tuo collo di bottiglia delle prestazioni (che probabilmente non è il fatto che hai usato il doppio). POI, se è ancora troppo lento per te, vedi dove puoi sacrificare un po 'di precisione e usa il galleggiante.
La principale differenza tra float e double è la precisione. Wikipedia contiene maggiori informazioni sulla precisione singola (float) e sulla doppia precisione .
Dipende molto dalla CPU, i compromessi più ovvi sono tra precisione e memoria. Con GB di RAM, la memoria non è un grosso problema, quindi è generalmente meglio usare double
s.
Per quanto riguarda le prestazioni, dipende molto dalla CPU. float
di solito otterranno prestazioni migliori di quelle double
su una macchina a 32 bit. Su 64 bit, double
i messaggi a volte sono più veloci, poiché è (di solito) la dimensione nativa. Tuttavia, ciò che conta molto di più della tua scelta dei tipi di dati è se puoi o meno trarre vantaggio dalle istruzioni SIMD sul tuo processore.
double ha una precisione maggiore, mentre i float occupano meno memoria e sono più veloci. In generale dovresti usare float a meno che tu non abbia un caso in cui non è abbastanza preciso.