Soll ich double oder float verwenden?

85

Was sind die Vor- und Nachteile der Verwendung eines in C ++ anstelle des anderen?

AraK
quelle
Hat jemand versucht, ein Array von Floats und ein Array von Doubles zu erstellen und festzustellen, ob tatsächlich 4 Bytes zwischen Mitgliedern auf Floats und 8 Bytes zwischen Mitgliedern auf Doubles vorhanden sind? Es ist möglich, dass ein 64-Bit-Compiler / Computer immer noch 8 Byte pro Mitglied für Floats reserviert, obwohl sie nicht so viel benötigen.
user3015682

Antworten:

103

Wenn Sie die wahre Antwort wissen möchten, sollten Sie lesen, was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte .

Kurz gesagt, obwohl doubleeine höhere Genauigkeit in der Darstellung möglich ist, würde es bei bestimmten Berechnungen zu größeren Fehlern kommen . Die "richtige" Wahl ist: Verwenden Sie so viel Präzision wie Sie brauchen, aber nicht mehr und wählen Sie den richtigen Algorithmus .

Viele Compiler führen ohnehin erweiterte Gleitkomma-Berechnungen im "nicht strengen" Modus durch (dh sie verwenden einen breiteren Gleitkommatyp, der in der Hardware verfügbar ist, z. B. 80-Bit- und 128-Bit-Gleitkomma). Dies sollte ebenfalls berücksichtigt werden. In der Praxis kann man kaum einen Unterschied in der Geschwindigkeit feststellen - sie sind sowieso einheimisch in der Hardware.

J-16 SDiZ
quelle
10
Ja. Mit modernen CPUs, die immer größere Speicherblöcke, parallele numerische Verarbeitungseinheiten und Pipeline-Architekturen vorab abrufen, ist das Geschwindigkeitsproblem wirklich kein Problem. Wenn Sie mit großen Mengen von Zahlen zu tun haben, kann der Größenunterschied zwischen einem 4-Byte-Float und einem 8-Byte-Double möglicherweise den Speicherbedarf beeinflussen.
Lavinio
5
Nun, SSE (oder eine beliebige Vertor-Gleitkommaeinheit) kann die doppelte Anzahl von Flops mit einfacher Genauigkeit im Vergleich zu doppelter Genauigkeit verarbeiten. Wenn Sie nur x87 (oder einen beliebigen skalaren) Gleitkommawert verwenden, spielt dies wahrscheinlich keine Rolle.
Greg Rogers
1
@ Greg Rogers: Compiler sind momentan nicht so schlau. Sofern Sie keine Raw-Assembly schreiben, gibt es keine großen Unterschiede. Und ja, dies kann sich ändern, wenn sich der Compiler weiterentwickelt.
J-16 SDiZ
Ein zusätzlicher Hinweis: Wenn Sie absolut keine Ahnung haben, wie die Daten aussehen (oder einfach keine Ahnung haben, welche Mathematik in den Links enthalten ist), verwenden Sie doublesie einfach - dies ist in den meisten Fällen sicherer.
J-16 SDiZ
2
Dieses Papier ist nicht kurz.
Jokoon
42

Verwenden Sie double, es sei denn, Sie haben einen bestimmten Grund, etwas anderes zu tun.

Es ist vielleicht überraschend, dass Double und nicht Float der "normale" Gleitkommatyp in C (und C ++) ist. Die Standard-Mathematikfunktionen wie sin und log verwenden doppelte Argumente und geben doppelte zurück. Ein normales Gleitkomma-Literal, wie wenn Sie 3.14 in Ihr Programm schreiben , hat den Typ double. Nicht schweben.

Auf typischen modernen Computern können Doubles genauso schnell wie Floats oder sogar noch schneller sein, sodass die Leistung selbst bei großen Berechnungen normalerweise kein zu berücksichtigender Faktor ist. (Und das müssten umfangreiche Berechnungen sein, sonst sollte Ihnen die Leistung nicht einmal in den Sinn kommen. Mein neuer i7-Desktop-Computer kann sechs Milliarden Multiplikationen von Doppel in einer Sekunde ausführen.)

Thomas Padron-McCarthy
quelle
27

Diese Frage ist nicht zu beantworten, da die Frage keinen Kontext hat. Hier sind einige Dinge, die die Auswahl beeinflussen können:

  1. Compiler-Implementierung von Floats, Doubles und Long Doubles. Der C ++ - Standard besagt:

    Es gibt drei Gleitkommatypen: float, double und long double. Der Typ double bietet mindestens so viel Präzision wie float, und der Typ long double bietet mindestens so viel Präzision wie double.

    Alle drei können also im Speicher dieselbe Größe haben.

  2. Anwesenheit einer FPU. Nicht alle CPUs haben FPUs und manchmal werden die Gleitkommatypen emuliert und manchmal werden die Gleitkommatypen einfach nicht unterstützt.

  3. FPU-Architektur. Die FPU des IA32 ist intern 80 Bit - 32-Bit- und 64-Bit-Floats werden beim Laden auf 80 Bit erweitert und beim Speichern reduziert. Es gibt auch SIMD, das vier 32-Bit-Floats oder zwei 64-Bit-Floats parallel ausführen kann. Die Verwendung von SIMD ist im Standard nicht definiert, daher wäre ein Compiler erforderlich, der komplexere Analysen durchführt, um festzustellen, ob SIMD verwendet werden kann, oder die Verwendung spezieller Funktionen (Bibliotheken oder Intrinsics). Das Ergebnis des internen 80-Bit-Formats ist, dass Sie leicht unterschiedliche Ergebnisse erzielen können, je nachdem, wie oft die Daten im RAM gespeichert werden (wodurch die Genauigkeit verloren geht). Aus diesem Grund optimieren Compiler Gleitkomma-Code nicht besonders gut.

  4. Speicherbandbreite. Wenn ein Double mehr Speicher benötigt als ein Float, dauert das Lesen der Daten länger. Das ist die naive Antwort. Bei einem modernen IA32 hängt alles davon ab, woher die Daten stammen. Wenn es sich im L1-Cache befindet, ist die Last vernachlässigbar, vorausgesetzt, die Daten stammen aus einer einzelnen Cache-Zeile. Wenn es mehr als eine Cache-Zeile umfasst, entsteht ein geringer Overhead. Wenn es von L2 ist, dauert es eine Weile länger, wenn es im RAM ist, dann ist es noch länger und schließlich, wenn es auf der Festplatte ist, ist es eine große Zeit. Die Wahl von float oder double ist daher weniger wichtig als die Art und Weise, wie die Daten verwendet werden. Wenn Sie eine kleine Berechnung für viele sequentielle Daten durchführen möchten, ist ein kleiner Datentyp vorzuziehen. Wenn Sie viel mit einem kleinen Datensatz rechnen, können Sie größere Datentypen mit erheblichen Auswirkungen verwenden. Wenn du' Wenn Sie sehr zufällig auf die Daten zugreifen, ist die Wahl der Datengröße unwichtig - Daten werden in Seiten / Cache-Zeilen geladen. Selbst wenn Sie nur ein Byte aus dem RAM benötigen, können 32 Bytes übertragen werden (dies hängt stark von der Architektur des Systems ab). Darüber hinaus könnte die CPU / FPU superskalar sein (auch bekannt als Pipeline). Obwohl ein Ladevorgang mehrere Zyklen dauern kann, kann die CPU / FPU damit beschäftigt sein, etwas anderes zu tun (z. B. eine Multiplikation), das die Ladezeit bis zu einem gewissen Grad verbirgt.

  5. Der Standard erzwingt kein bestimmtes Format für Gleitkommawerte.

Wenn Sie eine Spezifikation haben, führt Sie dies zur optimalen Auswahl. Ansonsten liegt es an der Erfahrung, was zu verwenden ist.

Skizz
quelle
16

Double ist genauer, wird jedoch auf 8 Bytes codiert. float ist nur 4 Bytes, also weniger Platz und weniger Präzision.

Sie sollten sehr vorsichtig sein, wenn Sie Double und Float in Ihrer Anwendung haben. Aufgrund dessen hatte ich in der Vergangenheit einen Fehler. Ein Teil des Codes verwendete float, während der Rest des Codes double verwendete. Das Kopieren von double in float und dann float in double kann zu Präzisionsfehlern führen, die große Auswirkungen haben können. In meinem Fall war es eine Chemiefabrik ... hoffentlich hatte es keine dramatischen Konsequenzen :)

Ich denke, dass die Ariane 6-Rakete vor ein paar Jahren wegen dieser Art von Fehler explodiert ist !!!

Überlegen Sie genau, welcher Typ für eine Variable verwendet werden soll

luc
quelle
3
Beachten Sie, dass 4/8 Byte für Float / Double nicht einmal garantiert sind, sondern von der Plattform abhängen. Es könnte sogar der gleiche Typ sein ...
Sleske
2
Der Ariane 5- Code versuchte, einen 64-Bit-Gleitkommawert, dessen Wert größer als 32.767 war, in eine 16-Bit-Ganzzahl mit Vorzeichen umzuwandeln. Dies erzeugte eine Überlaufausnahme, die dazu führte, dass die Rakete ihre Selbstzerstörungssequenz einleitete. Der fragliche Code war Code, der von einer älteren, kleineren Rakete wiederverwendet wurde.
cmwt
5

Ich persönlich mache die ganze Zeit das Doppelte, bis ich einige Engpässe sehe. Dann denke ich darüber nach, zu schweben oder einen anderen Teil zu optimieren

Eric
quelle
4

Dies hängt davon ab, wie der Compiler double implementiert. Es ist legal, dass Double und Float vom gleichen Typ sind (und dies ist auf einigen Systemen der Fall).

Wenn sie jedoch tatsächlich unterschiedlich sind, ist das Hauptproblem die Präzision. Ein Doppel hat aufgrund seines Größenunterschieds eine viel höhere Präzision. Wenn die von Ihnen verwendeten Zahlen normalerweise den Wert eines Floats überschreiten, verwenden Sie ein Double.

Mehrere andere Personen haben Leistungsprobleme erwähnt. Das wäre genau das Letzte auf meiner Liste der Überlegungen. Korrektheit sollte Ihre erste Überlegung sein.

JaredPar
quelle
2

Ich denke, unabhängig von den Unterschieden (die, wie alle betonen, Floats weniger Platz beanspruchen und im Allgemeinen schneller sind) ... hat jemand jemals Leistungsprobleme mit Double? Ich sage Double verwenden ... und wenn Sie später entscheiden "Wow, das ist wirklich langsam" ... finden Sie Ihren Leistungsengpass (was wahrscheinlich nicht die Tatsache ist, dass Sie Double verwendet haben). DANN, wenn es Ihnen immer noch zu langsam ist, sehen Sie, wo Sie etwas Präzision opfern und float verwenden können.

Tom
quelle
1

Es hängt stark von der CPU ab. Die offensichtlichsten Kompromisse bestehen zwischen Präzision und Speicher. Bei GB RAM ist der Speicher kein großes Problem, daher ist es im Allgemeinen besser, doubles zu verwenden .

Die Leistung hängt stark von der CPU ab. floats erzielt normalerweise eine bessere Leistung als doubles auf einem 32-Bit-Computer. Bei 64 Bit sind doubles manchmal schneller, da es (normalerweise) die native Größe ist. Viel wichtiger als die Auswahl der Datentypen ist jedoch, ob Sie die SIMD-Anweisungen auf Ihrem Prozessor nutzen können oder nicht.

Zifre
quelle
0

double hat eine höhere Präzision, während Floats weniger Speicher beanspruchen und schneller sind. Im Allgemeinen sollten Sie float verwenden, es sei denn, Sie haben einen Fall, in dem es nicht genau genug ist.

Tal Pressman
quelle
5
Auf typischen modernen Computern ist Double genauso schnell wie Float.
Thomas Padron-McCarthy