Unterschied zwischen Float und double

Ich weiß, dass ich über den Unterschied zwischen doppelten Präzision und Genauigkeit etc. gelesen habe. Aber sie sollten die gleichen Ergebnisse in den meisten Fällen Recht geben?

Ich war die Lösung eines Problems auf ein Programmierwettbewerb und es gab Berechnungen mit Gleitkommazahlen, die nicht wirklich groß waren, so dass ich beschloss, Schwimmen statt doppelt, und überprüfte ich es - ich war immer die richtigen Ergebnisse. Aber wenn ich die Lösung senden, es sagte, dass nur 1 von 10 Tests korrekt war. Ich überprüfte immer wieder, bis ich gefunden, dass mit Float nicht das gleiche mit double. Ich habe Doppel für die Berechnungen und Doppel für die Ausgabe und das Programm hat die gleichen Ergebnisse, aber diesmal es übergeben alle 10 Tests korrekt.

Ich wiederhole: die Ausgabe war der SAME, die Ergebnisse waren die gleichen, aber setzen Schwimmer hat nicht funktioniert - nur Doppelzimmer. Die Werte waren auch nicht so groß und das Programm gab die gleichen Ergebnisse über die gleichen Tests mit Float und Doppelzimmer, aber der online Richter akzeptiert nur die Doppel bereitgestellten Lösung.

Warum? Was ist der Unterschied?

Kommentar #1

Großen Unterschied.

Wie der Name schon sagt, ein double hat 2 x die Genauigkeit der float [1]. Im Allgemeinen hat ein Double 15 bis 16 Dezimalziffern Präzision, während float hat nur 7.

Diese Genauigkeitsverlust könnte zu Kürzungsfehler viel einfacher, z.B. zu schweben

    float a = 1.f / 81;
    float b = 0;
    for (int i = 0; i < 729; ++ i)
            b += a;
    printf("%.7g\n", b);   // prints 9.000023

während

    double a = 1.0 / 81;
    double b = 0;
    for (int i = 0; i < 729; ++ i)
            b += a;
    printf("%.15g\n", b);   // prints 8.99999999999996

Auch ist der maximale Wert des Schwimmers nur etwa 3e38 , aber doppelt ist über 1.7e308 , also mit float kann unendlich viel einfacher als das doppelte für etwas einfaches z.B. EDV 60 hit!.

Vielleicht die ihre Testfall enthält diese riesigen Zahlen, wodurch Ihr Programm zum Scheitern verurteilt.


Natürlich manchmal sogar double ist nicht genau genug, daher haben wir long double [1] (das obige Beispiel gibt 9.000000000000000066 auf Mac), aber alle diese Gleitkommawert Rundungsfehlern leiden, also wenn Präzision sehr wichtig ist (z.B. Geld Verarbeitung) verwenden Sie int oder eine Bruch-Klasse.


BTW, verwenden Sie keine += zu Summe viel von Fließkomma-Zahlen wie die Fehler schnell ansammeln. Bei Verwendung von Python verwenden fsum . Andernfalls versuchen Sie die Kahan Summierung Algorithmusimplementiert.


[1]: Die C und C++-Standards geben nicht die Darstellung von float , double und long double . Es ist möglich, dass alle drei als IEEE mit doppelter Genauigkeit implementiert. Dennoch für die meisten Architekturen (Gcc, MSVC; X 86, X 64, ARM) float ist in der Tat mit einer IEEE mit einfacher Genauigkeit Gleitkommazahl Punkt Anzahl (binary32), und double ist ein IEEE Gleitkommazahl mit doppelter Genauigkeit Anzahl (binary64) zeigen.

Kommentar #2

Hier ist was die Norm C99 (ISO-IEC 9899 6.2.5 § 10) oder C ++ 2003 (ISO-IEC 14882-2003 3.1.9 § 8) Normen zu sagen:

Es gibt drei Gleitkommatypen: float , double , und long double . Der Typ double bietet mindestens genauso viel Präzision als float , und der Typ long double bietet mindestens genauso viel Präzision als double . Die Menge der Werte des Typs float ist eine Teilmenge der Menge der Werte des Typs double ; die Menge der Werte des Typs double ist eine Teilmenge der Menge der Werte des Typs long double .

Der C++-standard fügt hinzu:

Die Wertdarstellung der Gleitkommatypen ist Implementierung definiert.

Ich würde vorschlagen, einen Blick auf die ausgezeichnete Was Every Computer Scientist sollten wissen über Floating-Point Arithmetic , die den Gleitkommazahlen IEEE-Standard in der Tiefe abdeckt. Erfahren Sie über die Darstellungsdetails, und Sie werden erkennen, dass es ist ein Kompromiss zwischen Helligkeit und Präzision. Die Genauigkeit der schwimmende zeigen Darstellung erhöht als die Helligkeit sinkt, daher Gleitkomma Zahlen zwischen-1 und 1 sind diejenigen mit den meisten Präzision.

Kommentar #3

  • Ein Double ist 64 und einfacher Genauigkeit (Ausleger) beträgt 32 Bit.
  • Double hat eine größere Mantisse (ganzzahliger Bits der reellen Zahl).
  • Etwaige Ungenauigkeiten werden kleinere im Double.

Kommentar #4

Angesichts eine quadratischen Gleichung: X2 − 4.0000000 X + 3.9999999 = 0, die genauen Wurzeln zu 10 Nachkommastellen sind, R1 = 2.000316228 und R2 = 1.999683772.

Mit float und double , wir können ein Testprogramm schreiben:

#include <stdio.h>
#include <math.h>

void dbl_solve(double a, double b, double c)
{
    double d = b*b - 4.0*a*c;
    double sd = sqrt(d);
    double r1 = (-b + sd) / (2.0*a);
    double r2 = (-b - sd) / (2.0*a);
    printf("%.5f\t%.5f\n", r1, r2);
}

void flt_solve(float a, float b, float c)
{
    float d = b*b - 4.0f*a*c;
    float sd = sqrtf(d);
    float r1 = (-b + sd) / (2.0f*a);
    float r2 = (-b - sd) / (2.0f*a);
    printf("%.5f\t%.5f\n", r1, r2);
}   

int main(void)
{
    float fa = 1.0f;
    float fb = -4.0000000f;
    float fc = 3.9999999f;
    double da = 1.0;
    double db = -4.0000000;
    double dc = 3.9999999;
    flt_solve(fa, fb, fc);
    dbl_solve(da, db, dc);
    return 0;
}  

Ausführen des Programms gibt mir:

2.00000 2.00000
2.00032 1.99968

Beachten Sie, dass die Zahlen nicht groß, aber Sie noch Stornierung bekommen Effekte mit float .

(In der Tat, die oben ist nicht der beste Weg zur Lösung quadratischer Gleichungen mithilfe entweder Einzel - oder Doppelzimmer Gleitkommazahlen mit einfacher Genauigkeit, aber die Antwort bleibt unverändert, auch wenn man eine stabilere Methodebenutzt.)

Kommentar #5

"Es gab Berechnungen mit Gleitkommazahlen, die waren nicht wirklich groß"

Die Größe der Zahlen ist irrelevant, es ist die Berechnung, die ausgeführt wird, die relevant sind.

Im Wesentlichen wird wenn Sie eine Berechnung durchführen sind und das Ergebnis eine irrationale Zahl oder wiederkehrende Decimal dann dort ist Fehler Rundung werden wenn diese Zahl in die endliche Größe Datastructure gequetscht ist, die du verwendest. Seit Doppel ist doppelt so groß wie float, dann der Rundungsfehler wird viel kleiner.

Der online-Test verwendet wahrscheinlich speziell Zahlen, die diese Art von Fehler führen würde und deshalb getestet, dass Sie den entsprechenden Typ im Code benutzt hatte.

Kommentar #6

Schwimmer haben weniger Präzision als verdoppelt. Auch wenn Sie bereits wissen, lesen Sie Was wir sollten wissen über Floating-Point Arithmetic , zum besseren Verständnis.

Kommentar #7

Bei Verwendung von Fließkomma-Zahlen, die Sie nicht vertrauen können, dass Ihre lokalen Tests genau das gleiche wie die Tests werden, die auf dem Server erfolgen. Der Umwelt und der Compiler unterscheiden sich wahrscheinlich auf Ihrem lokalen System und wo die abschließenden Tests ausgeführt werden. Ich habe dieses Problem viele Male gesehen, bevor in einigen TopCoder Wettbewerbe vor allem, wenn Sie versuchen, zwei schwimmende vergleichen Zahlen zeigen.

Kommentar #8

Typ Float, 32 Bit lang, hat eine Genauigkeit von 7 stellen. Während es Werte sehr große oder sehr kleine Bereich speichern kann (+/-3.4 * 10 ^ 38 oder * 10 ^-38), es hat nur 7 signifikanten Stellen.

Doppelzimmer, Typ 64 Bits lang, hat einen größeren Bereich (* 10 ^ +/-308) und 15 Stellen Genauigkeit.

lange Double ist nominell 80 Bits, obwohl eine bestimmten Compiler/OS Paarung es als 12-16 Bytes für Ausrichtung Zwecke speichern kann. Die lange Double hat einen Exponenten, die einfach lächerlich riesig, und 19 Ziffern Genauigkeit haben sollte. M$, in ihrer unendlichen Weisheit, begrenzt auf 8 Byte, identisch mit einfachen Double lange verdoppelt.

Generell zeigen nur Verwendung Typ double, wenn Sie eine Gleitkommazahl doppelter Genauigkeit benötigen Wert/Variable. Literal Gleitkommawerte in Ausdrücken verwendet werden als Doppelzimmer standardmäßig behandelt, und die meisten der Mathefunktionen, die floating Point Werte zurückgeben zurück verdoppelt. Sie sparen sich viele Kopfschmerzen und Typecastings, wenn Sie nur Doppelzimmer.

Kommentar #9

Der eingebaute Vergleich, die Operationen unterscheiden sich wie wenn man 2 Zahlen mit schwebenden Ziffern vergleicht, kann Diffrence im Datentyp (d.h. Float oder Double) verschiedene Ergebnisse

Tags lesen