Problembeschreibung
Bei der Verwendung von Java zur Berechnung der schwimmenden Punktzahlen im Projekt wurde festgestellt, dass für Berechnungen wie 4,015*100 das Ergebnis nicht das erwartete 401,5, sondern 401.499999999999999999999999999994 war. Eine so lange Anzahl von Ziffern ist für die Anzeige unfreundlich.
Ursache des Problems: Schwebungspunktzahl Darstellung
Nachdem ich relevante Informationen konsultierte, stellte ich fest, dass der Grund dafür ist, dass die schwimmenden Punktzahlen im Computer nicht vollständig ausgedrückt werden können. Zum Beispiel speichert der Computer für einen Doppel -Typ 38414.4 es wie folgt:
In Binary konvertieren: 10010110000110.0110011001100110011001100110011001100
In ein Thema verwandeln
Lernen Sie die Zählung
Das Doppelcodierungsformat lautet wie folgt:
Doppelzeichenbit 1 Zifferner Bühnencode 11 Ziffern Mantissa 52 Ziffern
Symbol Bit: Positive Zahl ist 0
Bestellcode: 15 ist eine positive Zahl, daher ist das höchste Bit 1, das niedrigste Bit ist minus 1, das ist 10000001110
Mantissue: Entfernen Sie den Standard 1 des höchsten Bits, das 0010110000110011001100110011001100110011001100 ist
Kombiniert ist die endgültige Codierung: 0 1000001110 001011000011001100110011001100110011001100110011001100
Von hier aus können wir erkennen, dass der Hauptgrund dafür ist, dass die Binärcodierung den fraktionalen Teil unmöglich macht, genau genau auszudrücken, z. B. 0,4 = 0,25 + 0,125 + ..., was nur unendlich eng sein kann. Daher treten Genauigkeitsfehler bei der Berechnung der schwimmenden Punktzahlen auf.
Lösung: hohe Präzision
BigDecimal in Java kann die Operationen der schwimmenden Punktzahl mit willkürlicher Präzision unterstützen. In dem Buch "Effektiver Java" wird empfohlen, dass Float und Double für wissenschaftliche Berechnungen oder technische Berechnungen verwendet werden, während Java.math.bigdecimal in kommerziellen Berechnungen verwendet wird.
Es gibt viele Baumethoden für BigDecimal, wie BigDecimal (doppelt) und BigDecimal (String). Es ist zu beachten, dass die Konstruktionsparameter String -Typ sind, um sicherzustellen, dass die Genauigkeit nicht verloren geht, da der Doppelart selbst unvollständig genau ist. Daher muss es wie folgt geschrieben werden: BigDecimal ("0,02").
Grundlegende Operationen des Doppelarts finden Sie in BigDecimal. Darüber hinaus kann BigDecimal auch zur Formatierung der Ausgabe mit Numberformat verwendet werden.
BigDecimal wird bei Operationen neue BigDecimal -Objekte erzeugen, sodass dies im Vergleich zum Doppel mehr Leistungsaufwand bringt.
Eine vorläufige Studie zur Implementierung mit hoher Präzision
Wie kann BigDecimal in der Lage sein, willkürliche Präzision zu repräsentieren? Hier ist nur eine vorläufige Analyse.
Schauen wir uns zunächst die Implementierung von BigInenger an. Der gewöhnliche INT -Typ beträgt 32 Bit, daher gibt es eine Reichweite. BigInteger hat das Mitglied der Mitgliedsvariable int [], so dass das längere Int -Array es ermöglicht, Ganzzahlen jeder Größe darzustellen.
Schauen wir uns die Implementierung von BigDecimal an. Seine offizielle Einführung besagt, dass jedes Bigdecimal als ungekalktes × 10^-Scale dargestellt werden kann. UncaledValue ist eine ganze Größe, die der Mitgliedsvariablen -Biginteger -Intval im Quellcode entspricht. Die Skala ist die Reihenfolge, die der Variablen -INT -Skala im Quellcode entspricht. Auf diese Weise wird BigDecimal basierend auf BigInteger implementiert.
Das obige ist die Lösung für das Problem der schwimmenden Punktgenauigkeit in Java, die Ihnen vom Herausgeber vorgestellt wurde. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht.