** Der Code in diesem Artikel ist in Java SE 8 geschrieben. ** **.
Wenn Sie Variablen vom Typ Double mit ==
vergleichen, werden Sie darauf hingewiesen, dass dies mit statischen Analysewerkzeugen nicht gut ist, sondern ein Fehler ist.
Ich war neugierig auf verschiedene Dinge und versuchte (jetzt) herauszufinden, wie man mit Gleitkommazahlen umgeht.
Wenn Sie sich nicht für die Leistung interessieren, verwenden Sie Big Decimal. Wenn Sie das Design der Datenbank ändern können, können Sie die Ziffern verschieben und mit int oder long behandeln.
Bitte schauen Sie sich zunächst diesen an.
Code
double doubleValue1 = 1.0d;
double doubleValue2 = 0.9d;
double resultValue = doubleValue1 - doubleValue2;
System.out.println("doubleValue1: " + doubleValue1);
System.out.println("doubleValue2: " + doubleValue2);
System.out.println(resultValue == 0.1d);
System.out.println("Subtraktionsergebnis: " + resultValue);
** Ausführungsergebnis **
doubleValue1: 1.0
doubleValue2: 0.9
false
Subtraktionsergebnis: 0.09999999999999998
Das Subtraktionsergebnis soll großartig sein.
Computer verarbeiten Zahlen binär.
Einige Brüche, wie beispielsweise "0,9", werden jedoch zu kreisförmigen Brüchen, wenn sie binär ausgedrückt werden. Da der Computer nur eine endliche Anzahl von Ziffern verarbeiten kann, wird er auf einen geeigneten Wert gerundet und es tritt ein Fehler auf.
Da es subtil mit einem anderen Wert als "0,9" subtrahiert wird, wird das obige Ergebnis erhalten. Im Buchhaltungssystem kann sogar ein Fehler von 1 Yen zu einer Klage führen, was ein großes Problem darstellt.
Verwenden Sie BigDecimal, um das Problem zu lösen!
Code
BigDecimal bigDecimalValue1 = new BigDecimal("1.0");
BigDecimal bigDecimalValue2 = new BigDecimal("0.9");
BigDecimal bigDecimalResultValue = bigDecimalValue1.subtract(bigDecimalValue2);
System.out.println("bigDecimalValue1: " + bigDecimalValue1);
System.out.println("bigDecimalValue2: " + bigDecimalValue2);
System.out.println(bigDecimalResultValue.equals(new BigDecimal("0.1")));
System.out.println("Subtraktionsergebnis: " + bigDecimalResultValue);
** Ausführungsergebnis **
bigDecimalValue1: 1.0
bigDecimalValue2: 0.9
true
Subtraktionsergebnis: 0.1
BigDecimal enthält den Wert in Form der Verschiebung des Bruchteils zum ganzzahligen Teil. Da alle Ganzzahlen durch endliche Binärzahlen dargestellt werden können, kann BigDecimal verwendet werden, um Gleitkommazahlen genau zu berechnen und zu vergleichen.
Die Methode lautet Siehe offizielle Referenz.
Da BigDecimal ein Referenztyp ist, ist er natürlich langsamer als grundlegende Datentypoperationen. Lass uns nachsehen.
Code
double doubleValue1 = 1.0d;
double doubleValue2 = 0.9d;
long startDouble = System.currentTimeMillis();
//100 Millionen Abzüge(double)
for(int i = 0; i < 100_000_000 ; i++){
double resultValue = doubleValue1 - doubleValue2;
}
long endDouble = System.currentTimeMillis();
BigDecimal bigDecimalValue1 = new BigDecimal("1.0");
BigDecimal bigDecimalValue2 = new BigDecimal("0.9");
long startBigDecimal = System.currentTimeMillis();
//100 Millionen Abzüge(BigDecimal)
for(int i = 0; i < 100_000_000 ; i++){
BigDecimal bigDecimalResultValue = bigDecimalValue1.subtract(bigDecimalValue2);
}
long endBigDecimal = System.currentTimeMillis();
System.out.println("doppeltes Messergebnis: " + (endDouble - startDouble) + "ms");
System.out.println("bigDecimal Messergebnis: " + (endBigDecimal - startBigDecimal) + "ms");
** Ausführungsergebnis **
doppeltes Messergebnis: 3ms
bigDecimal Messergebnis: 314ms
Es gab einen beträchtlichen Unterschied. Immerhin ist der Basisdatentyp schnell!
Ich persönlich frage mich, ob es kein Problem mit Big Decimal gibt, es sei denn, es gibt viele Schleifen oder es ist Leistung erforderlich.
Es gibt Zeiten, in denen Sie sich nicht zwingen müssen, Gleitkommazahlen zu verwenden.
Angenommen, Sie haben ein System, das Ihr Gewicht bis zur ersten Ziffer des Bruchs registriert. Selbst wenn es mit 65,3 kg in Bezug auf die Schnittstelle empfangen wird, kann es normal mit int verarbeitet werden, wenn es im vorgelagerten Teil des Programms um eins verschoben und intern mit 653 behandelt wird. Frei von mühsamer Gleitkomma-Verarbeitung!
Dies wirkt sich jedoch auch auf die Spaltendefinition der Datenbank aus. Daher ist es gut, in der Entwurfsphase eine feste Entscheidung zu treffen.
Recommended Posts