Was ich aus der Java-Geldberechnung gelernt habe

Vorwort

Ich verwende Java 8 in meinem Projekt.

Der Anfang der Sache

Ich codiere in Java, was eine Geldberechnung beinhaltet, und der auf dem Bildschirm angezeigte Wert ist

299.999999999999988897769753748434595763683319091796875000

Ich bin auf ein Ereignis gestoßen, das leicht davon abwich. Ich schäme mich zu sagen, dass ich die Logik geschrieben habe, um den (?) Betrag zum ersten Mal richtig zu berechnen Ich ging weiter, während ich den Grund dafür untersuchte.

Auf der Suche nach dem Verbrecher

In der ersten Stufe der Verarbeitung wird beispielsweise der Betrag mit einem Prozentsatz multipliziert

//Prozentsatz und Menge, die von einem Modell erhalten wurden
double d = 0.3;
BigDecimal bd = new BigDecimal("1000");
//Berechnung
BigDecimal bd2 = bd.multiply(new BigDecimal(d));
System.out.println(bd2); // 299.999999999999988897769753748434595763683319091796875000

Sie haben eine BigDecimal-Instanz erstellt, indem Sie das doppelte Argument an den Konstruktor übergeben haben. Als Ergebnis des Abrufs aus der Datenbank wurde das in der Servive-Klasse verwendete Modellfeld als Doppeltyp definiert.

Warum ist es aus?

Obwohl es im Code dezimal definiert ist, wird es intern binär behandelt Werte, die binäre und kreisförmige Brüche sind (z. B. doppelt 0,3), werden gerundet, dh es tritt ein Fehler auf.

Screenshot 2018-10-16 18.37.13.png durch Bezugnahme

Das ist nicht gut

double d = 3.3 / 1.1 //Ich möchte, dass du 3 aber 2 bist.9999999999999996

Bestätigen Sie erneut, wie Big Decimal hier verwendet wird (Schweiß)

Ich habe die Referenz vorerst gelesen. https://docs.oracle.com/javase/jp/8/docs/api/java/math/BigDecimal.html

- add  - subtract  - multiply  - divide Führen Sie vier Regeln mit Methoden wie z. Geben Sie im Rundungsmodus Rundung / Rundung / Rundung an. Die Logik war diesmal nicht so kompliziert, also habe ich keine komplizierten Methoden angewendet.

Es ist gut, dass es nicht gut ist.

//Instanzgenerierung jedes Mal, ineffizient
BigDecimal b1 = new BigDecimal(10); //Nicht gut
//Verwenden Sie den Cache valueOf()
BigDecimal b2 = BigDecimal.valueOf(10); //gut

//∵ Ein Fehler tritt auf, wenn die Binärzahl ein Kreisbruch ist.
BigDecimal b3 = new BigDecimal(0.3); //Nicht gut
//Aus einer Zeichenfolge generieren
BigDecimal b4 = new BigDecimal("0.3"); //gut
//Wenn Sie den Wert von double in BigDecimal konvertieren möchten
BigDecimal b5 = BigDecimal.valueOf(0.3); //(Ich möchte diese Konvertierung nach Möglichkeit nicht implementieren.)

--BigDecimal # ROUND_xxxx-Serie ist in Java 9 oder höher veraltet. Verwenden wir RoundingMode (Java8 wird im aktuellen Projekt verwendet, aber ich werde mir dessen im Vorgriff auf ein Versions-Upgrade bewusst sein).

Referenz-URL

http://javazuki.com/articles/bigdecimal-usage.html#_roundingmode https://qiita.com/TKR/items/52635175654b9b818b89

2019/11/12 Persönliches Memo

Fall, in dem der Größenvergleich (compareTo ()) nicht jedes Mal verstanden wird

BigDecimal three = BigDecimal.valueOf(3);
BigDecimal five = BigDecimal.valueOf(5);

int hoge  = three.compareTo(five); // -1 
int piyo = three.compareTo(three); // 0
int fuga = five.compareTo(three); // 1

Recommended Posts

Was ich aus der Java-Geldberechnung gelernt habe
Was ich aus dem Studium von Rails gelernt habe
Was ich mit Java Silver gelernt habe
Was ich gelernt habe
[Anmerkung] Was ich in einem halben Jahr von unerfahrenen (Java) gelernt habe
[Anmerkung] Was ich in einem halben Jahr von unerfahrenen (Java) gelernt habe (3)
Was ich aus Java gelernt habe, funktioniert mit Visual Studio Code
Was ich gelernt habe ② ~ Mock ~
Was ich gelernt habe ~ ~ DJUnit ~
Was ich in Java gelernt habe (Teil 2) Was sind Variablen?
Was ich über Java 8 recherchiert habe
Was ich über Java 6 recherchiert habe
Was ich über Java 9 recherchiert habe
Was ich in Java gelernt habe (Teil 3) Anweisung zur Ausführung von Anweisungen
Was ich beim Erstellen eines Servers in Java gelernt habe
Was ich über Java 7 recherchiert habe
Was ich über Kotlin gelernt habe
Was ich über Java 5 recherchiert habe
Was ich in Java gelernt habe (Teil 4) Bedingte Verzweigung und Wiederholung
Was ich über Java-Lernen recherchiert habe
Was ich in Java gelernt habe (Teil 1) Java-Entwicklungsablauf und Überblick
Woran ich dachte, als ich anfing, von Java nach Kotlin zu migrieren
Bedeutung der aus der Java Collection gelernten Schnittstelle
Nehmen Sie, was Sie über Java-Reflexion gelernt haben
[Rails] Was ich aus einem kleinen Stolperstein bei der Verwendung von Vorfahren gelernt habe
Zusammenfassung dessen, was ich über Spring Boot gelernt habe
Was ist java
[Java] Was soll ich zum Schreiben von Dateien verwenden?
Ich habe versucht, eine Java-Methode von ABCL zu verwenden
Methodenname der statischen Factory-Methode, die aus Java 8 gelernt wurde
Was ist Java <>?
Was ist java
Was ich getan habe, als ich Java zu Kotlin konvertiert habe
Ich möchte schnell von Java nach SQLite schreiben
Zusammenfassung dessen, was ich in Spring Batch gelernt habe
[Java] Ich möchte die Differenz zum Datum berechnen
Ich werde sowieso schreiben, was ich über Docker gelernt habe (zweite)
6 Funktionen, die ich nach meiner Rückkehr von Scala nach Java verpasst habe
Ich habe versucht, nativen Java / Objective-C-Code von Flutter aus aufzurufen
Ich werde sowieso schreiben, was ich über Docker gelernt habe (zuerst)
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat
Änderungen von Java 8 zu Java 11
Summe von Java_1 bis 100
Java Learning 2 (Lernen Sie die Berechnungsmethode)
Ich habe zuerst Java touched berührt
Eval Java-Quelle von Java
Ich habe zuerst Java touched berührt
Greifen Sie über Java auf API.AI zu
Von Java zu Ruby !!
Was ist Java-Technologie?
Ich habe zuerst Java berührt
Was ist Java API-Java?
[Java] Was ist flatMap?
[Java] Was ist ArrayList?
[JDBC] Ich habe versucht, von Java aus auf die SQLite3-Datenbank zuzugreifen.
Ich bin von Rails gekommen und wusste nicht, was [attr_accessor] ist