2008-08-25 11 views
4

Ich tat dies Nur für Tritte (also, nicht genau eine Frage, ich kann sehen, die Downmodding passiert bereits), aber anstelle von Googles neu gefunden inability zu tun mathcorrectly (überprüfen Sie es! Nach google 500,000,000,000,002 - 500,000,000,000,001 = 0), Ich dachte mir, ich würde das Folgende in C versuchen, um ein wenig Theorie zu machen.Der Google Calculator-Glitch, könnte float vs. double ein möglicher Grund sein?

int main() 
{ 
    char* a = "399999999999999"; 
    char* b = "399999999999998"; 

    float da = atof(a); 
    float db = atof(b); 

    printf("%s - %s = %f\n", a, b, da-db); 

    a = "500000000000002"; 
    b = "500000000000001"; 
    da = atof(a); 
    db = atof(b); 
    printf("%s - %s = %f\n", a, b, da-db); 
} 

Wenn Sie dieses Programm ausführen, erhalten Sie die folgenden

399999999999999 - 399999999999998 = 0.000000 
    500000000000002 - 500000000000001 = 0.000000 

Es scheint wie Google einfache 32-Bit-Floating-Präzision (der Fehler hier) verwendet, wenn Sie Schwimmer für Doppel in dem Schalter Über dem Code beheben Sie das Problem! Könnte das sein?

/mp

Antwort

4

Für mehr von dieser Art von Albernheit sehen diesen schönen Artikel zu Windows-Rechner gehört.

When you change the insides, nobody notices

Die Innereien von Calc - das arithmetische Motor - wurde komplett weggeworfen und von Grund auf neu geschrieben. Die IEEE Fließkomma-Standardbibliothek wurde durch eine beliebige arithmetische Bibliothek ersetzt. Dies wurde getan, nachdem Leute ha-ha Artikel darüber geschrieben, wie Calc konnte keine Dezimalarithmetik richtig tun, dass zum Beispiel Berechnung 10.21 - 10.2 ergab 0.0100000000000016.

2

Es scheint wie Google einfache 32-Bit-Floating-Genauigkeit (Fehler werden hier) verwendet, wenn Sie Schwimmer für Doppel in dem obigen Code zu wechseln, beheben Sie das Problem! Könnte das sein?

Nein, Sie verschieben nur das Problem. Doppel zeigen immer noch das gleiche Problem, nur mit größeren Zahlen.

1

@ebel

darüber nachzudenken, haben Sie 64 Bit eine Zahl größer als 2^64 (double.maxvalue) darstellt, so wird Ungenauigkeit erwartet.

2^64 ist nicht der Maximalwert eines Double. 2^64 ist die Anzahl der eindeutigen Werte, die ein Double (oder jeder andere 64-Bit-Typ) enthalten kann. Double.MaxValue entspricht 1,79769313486232e308.

Ungenauigkeit mit Fließkommazahlen stammt nicht von Werten größer als Double.MaxValue (was unmöglich ist, ausgenommen Double.PositiveInfinity). Es kommt daher, dass der gewünschte Wertebereich einfach zu groß ist, um in den Datentyp zu passen. Daher verzichten wir auf Präzision im Austausch für eine größere effektive Reichweite. In essense geben wir signifikante Ziffern für einen größeren Exponentenbereich ab.

@DrPizza

Nicht einmal; Die IEEE-Kodierungen verwenden mehrere Kodierungen für die gleichen Werte. Insbesondere wird NaN durch einen Exponenten aller Bits-1 und dann irgendeinen Nicht-Null-Wert für die Mantisse dargestellt. So gibt es 252 NaNs für Doppel, 223 NaNs für Singles.

Wahr. Ich habe doppelte Codierungen nicht berücksichtigt. Es gibt tatsächlich 2 -1 NaNs für Doppel und 2 -1 NaNs für Singles, obwohl. : p

0

2^64 ist nicht der Maximalwert eines Double. 2^64 ist die Anzahl der eindeutigen Werte, die ein Double (oder jeder andere 64-Bit-Typ) enthalten kann. Double.MaxValue ist gleich 1.79769313486232e308.

Nicht einmal; Die IEEE-Kodierungen verwenden mehrere Kodierungen für die gleichen Werte. Insbesondere wird NaN durch einen Exponenten aller Bits-1 dargestellt, und dann jeder Wert ungleich null für die Mantisse. Als solche gibt es 2 NaNs für Doppel, 2 NaNs für Singles.

0

Wahr. Ich habe doppelte Codierungen nicht berücksichtigt. Es gibt tatsächlich 252-1 NaNs für Doppel und 223-1 NaNs für Singles, obwohl. : p

Doh, vergessen, die Unendlichkeiten zu subtrahieren.

0

Die grobe Schätzung Version dieses Problems, das ich gelernt habe, ist, dass 32-Bit-Gleitkommazahlen geben Sie 5 Stellen der Genauigkeit und 64-Bit-Gleitkommazahlen geben Sie 15 Stellen der Genauigkeit. Dies hängt natürlich davon ab, wie die Floats codiert sind, aber es ist ein ziemlich guter Ausgangspunkt.