Hier ist, was in binären los ist. Wie wir wissen, können einige Gleitkommawerte nicht genau binär dargestellt werden, selbst wenn sie genau dezimal dargestellt werden können. Diese 3 Zahlen sind nur Beispiele für diese Tatsache.
Mit diesem Programm gebe ich die hexadezimalen Darstellungen jeder Zahl und die Ergebnisse jeder Addition aus.
public class Main{
public static void main(String args[]) {
double x = 23.53; // Inexact representation
double y = 5.88; // Inexact representation
double z = 17.64; // Inexact representation
double s = 47.05; // What math tells us the sum should be; still inexact
printValueAndInHex(x);
printValueAndInHex(y);
printValueAndInHex(z);
printValueAndInHex(s);
System.out.println("--------");
double t1 = x + y;
printValueAndInHex(t1);
t1 = t1 + z;
printValueAndInHex(t1);
System.out.println("--------");
double t2 = x + z;
printValueAndInHex(t2);
t2 = t2 + y;
printValueAndInHex(t2);
}
private static void printValueAndInHex(double d)
{
System.out.println(Long.toHexString(Double.doubleToLongBits(d)) + ": " + d);
}
}
Die printValueAndInHexMethode ist nur ein Hex-Drucker-Helfer.
Die Ausgabe ist wie folgt:
403787ae147ae148: 23.53
4017851eb851eb85: 5.88
4031a3d70a3d70a4: 17.64
4047866666666666: 47.05
--------
403d68f5c28f5c29: 29.41
4047866666666666: 47.05
--------
404495c28f5c28f6: 41.17
4047866666666667: 47.050000000000004
Die ersten 4 Zahlen sind x, y, zund shexadezimalen Darstellungen s‘. In der IEEE-Gleitkomma-Darstellung repräsentieren die Bits 2-12 den binären Exponenten , dh die Skala der Zahl. (Das erste Bit ist das Vorzeichenbit und die verbleibenden Bits für die Mantisse .) Der dargestellte Exponent ist tatsächlich die Binärzahl minus 1023.
Die Exponenten für die ersten 4 Zahlen werden extrahiert:
sign|exponent
403 => 0|100 0000 0011| => 1027 - 1023 = 4
401 => 0|100 0000 0001| => 1025 - 1023 = 2
403 => 0|100 0000 0011| => 1027 - 1023 = 4
404 => 0|100 0000 0100| => 1028 - 1023 = 5
Erster Satz von Ergänzungen
Die zweite Zahl ( y) ist kleiner. Wenn Sie diese beiden Zahlen addieren x + y, werden die letzten 2 Bits der zweiten Zahl ( 01) außerhalb des Bereichs verschoben und nicht in die Berechnung einbezogen.
Der zweite Zusatz fügt x + yund zund fügt zwei Zahlen derselben Skala hinzu.
Zweiter Satz von Ergänzungen
Hier x + ztritt zuerst auf. Sie haben den gleichen Maßstab, aber sie ergeben eine Zahl, die höher ist:
404 => 0|100 0000 0100| => 1028 - 1023 = 5
Die zweite Addition fügt x + zund hinzu y, und jetzt werden 3 Bits entfernt y, um die Zahlen ( 101) hinzuzufügen . Hier muss es eine Runde nach oben geben, da das Ergebnis die nächste Gleitkommazahl ist: 4047866666666666für den ersten Satz von Ergänzungen vs. 4047866666666667für den zweiten Satz von Ergänzungen. Dieser Fehler ist signifikant genug, um im Ausdruck der Gesamtsumme angezeigt zu werden.
Seien Sie abschließend vorsichtig, wenn Sie mathematische Operationen an IEEE-Zahlen ausführen. Einige Darstellungen sind ungenau und werden noch ungenauer, wenn die Skalen unterschiedlich sind. Addiere und subtrahiere Zahlen ähnlichen Maßstabs, wenn du kannst.
(2.0^53 + 1) - 1 == 2.0^53 - 1 != 2^53 == 2^53 + (1 - 1). B. ). Daher ja: Seien Sie vorsichtig bei der Auswahl der Reihenfolge der Beträge und anderer Operationen. Einige Sprachen bieten eine integrierte Funktion zum Ausführen von "hochpräzisen" Summen (z. B. Pythonsmath.fsum). Daher sollten Sie diese Funktionen möglicherweise anstelle des naiven Summenalgorithmus verwenden.