[Java] Big Decimal richtig verwenden ~ 2018 ~

In Java9 wurde das "BigDecimal # ROUND_ ~" - System endlich zu "@ Deprecated". In Blogs und Einträgen, die "BigDecimal" erklären, wird "BigDecimal # setScale", "BigDecimal # dividieren" usw. mit dem System "BigDecimal # ROUND_ ~" erklärt. Was meinst du? Es ist alles "@ veraltet" in Java 9, oder? Ich habe beschlossen, einen Artikel zu schreiben, weil ich mich in letzter Zeit unwohl fühle.

Zunächst von den Grundlagen.

Generierungs- / Fabrikmethode

Basic

Es wird im Wesentlichen mit der folgenden Methode generiert.

BigDecimal value = BigDecimal.valueOf(1234.567);//Erzeugung aus einem numerischen System
BigDecimal value = new BigDecimal("1234.567");//Aus einer Zeichenfolge generiert

Verwenden Sie diese, da bereits "0", "1", "10" definiert sind.

BigDecimal.ZERO
BigDecimal.ONE
BigDecimal.TEN

Hinweise zur Generierung aus Strings

Die Erzeugung aus der Zeichenkette erfolgt durch die Zeichenkette in scale.

System.out.println(new BigDecimal("1234.567").scale());  // → 3
System.out.println(new BigDecimal("1234.56700").scale());// → 5

Aus numerischen Werten erzeugtes NG-Muster

Verwenden Sie BigDecimal # valueOf, um aus einer Zahl (double) zu generieren. Es wäre lächerlich, es mit "neu" zu generieren.

BigDecimal value = new BigDecimal(1234.567);// NG!!Erzeugung aus einem numerischen System
System.out.println(value);// → 1234.5670000000000072759576141834259033203125

ResultSet#getBigDecimal Wenn Sie von "ResultSet" kommen, gibt es "ResultSet # getBigDecimal". Verwenden Sie diese Option.

BigDecimal value = rs.getBigDecimal("COL");

Das Folgende ist nutzlos, also NG

BigDecimal value = BigDecimal.valueOf(rs.getDouble("COL"));
BigDecimal value = new BigDecimal(rs.getString("COL"));

Vier Regeln

Hinzufügen

BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);

// value = a + b
BigDecimal value = a.add(b);

System.out.println(value);// 579

Subtrahieren

BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);

// value = a - b
BigDecimal value = a.subtract(b);

System.out.println(value);// -333

Multiplizieren

BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);

// value = a * b
BigDecimal value = a.multiply(b);

System.out.println(value);// 56088

10 mal, 100 mal usw.

Verwenden Sie "BigDecimal # scaleByPowerOfTen".

BigDecimal src = BigDecimal.valueOf(0.123);
BigDecimal value = src.scaleByPowerOfTen(2);//Hundertfach(10 im Quadrat)
System.out.println(value);// 12.3

Es ist viel sauberer als "src.multiply (BigDecimal.valueOf (100))", und Sie müssen keine Instanz von "100" erstellen.

Negativ (Vorzeichenumkehrung)

Verwenden Sie "BigDecimal # negate".

BigDecimal src = BigDecimal.valueOf(123);
BigDecimal value = src.negate();
System.out.println(value);// -123

Bitte hören Sie auf, Folgendes zu schreiben.

BigDecimal value = src.multiply(BigDecimal.valueOf(-1));

Teilung

import java.math.RoundingMode;
//・ ・ ・

BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);

// value = a / b
BigDecimal value = a.divide(b, 3 /* ← scale */, RoundingMode.HALF_UP /*← Rundung*/);

System.out.println(value);// 0.270

Methoden, die durch "RoundingMode" ersetzt werden können, sind nicht verfügbar

Der folgende Schreibstil ist NG

BigDecimal value = a.divide(b, 3, BigDecimal.ROUND_HALF_UP);

Weitere Informationen zum Rundungsmodus finden Sie unter [unten](# Rundungsmodus).

Geben Sie "Skala" an

Es gibt auch eine "BigDecimal # divid" -Methode, die keine "Skala" angibt. Wenn es nicht teilbar ist, tritt eine "ArithmeticException" auf, daher ist es besser, die von "scale" angegebene Version zu verwenden.

1/10, 1/100 usw.

Verwenden Sie "BigDecimal # scaleByPowerOfTen".

BigDecimal src = BigDecimal.valueOf(8);
BigDecimal value = src.scaleByPowerOfTen(-2);// 1/100(10-Kariert)
System.out.println(value);// 0.08

Rundung / Rundung / Aufrundung

import java.math.RoundingMode;
//・ ・ ・


BigDecimal src = BigDecimal.valueOf(123.456);

//Rundung
BigDecimal value = src.setScale(2, RoundingMode.HALF_UP);
System.out.println(value); // → 123.46

//Zusammenfassen
BigDecimal value = src.setScale(2, RoundingMode.UP);

//Kürzen
BigDecimal value = src.setScale(2, RoundingMode.DOWN);

Methoden, die durch "RoundingMode" ersetzt werden können, sind nicht verfügbar

Der folgende Schreibstil ist NG

BigDecimal value = src.setScale(2, BigDecimal.ROUND_HALF_UP);

Weitere Informationen zum Rundungsmodus finden Sie unter [unten](# Rundungsmodus).

Stringifizierung

BigDecimal#toPlainString BigDecimal # toString kann exponentiell sein, daher denke ich, dass es besser ist , BigDecimal # toPlainString zu verwenden.

BigDecimal value = new BigDecimal("0.0000001");
System.out.println(value.toString());     // → 1E-7
System.out.println(value.toPlainString());// → 0.0000001

Jackson hat auch die Option, "toPlainString" zu verwenden. JsonGenerator.Feature.html#WRITE_BIGDECIMAL_AS_PLAIN

Entfernen Sie "0" am Ende der Fraktion

Sowohl "BigDecimal # toString" als auch "BigDecimal # toPlainString" berücksichtigen "scale" in der Zeichenfolge und bleiben auch dann erhalten, wenn auf den Bruch "0" folgt. Wenn Sie dies deaktivieren möchten, verwenden Sie "BigDecimal # stripTrailingZeros". Sie müssen nicht hart mit regulären Ausdrücken arbeiten.

BigDecimal value = new BigDecimal("1.000000");
		
System.out.println(value);                     // → 1.000000
System.out.println(value.stripTrailingZeros());// → 1

int longdouble

BigDecimal value = BigDecimal.valueOf(12345);
int i = value.intValue();
long l = value.longValue();
double d = value.doubleValue();

Es gibt auch float und BigInteger.

Version zur Toleranzprüfung

Es gibt eine Version der Konvertierung in Ganzzahlen, die eine Ausnahme auslöst, wenn Informationen vorliegen, die aus Toleranzgründen verloren gehen. Umgekehrt wird die normale Version ignoriert, auch wenn Informationen verloren gehen.

int i = value.intValueExact();
long l = value.longValueExact();

Es gibt auch "Byte" -, "Short" - und "BigInteger" -Versionen der "-ValueExact" -Methodenfamilie.

Spielvergleich

Normaler Vergleich

Da "BigDecimal # equals" "false" zurückgibt, wenn "scale" nicht übereinstimmt, Wenn Sie ein System schreiben, an dem Sie nicht interessiert sind, z. B. "scale", sollten Sie beurteilen, ob das Ergebnis von "compareTo" mit "0" übereinstimmt.

BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2

System.out.println(value1.equals(value2));        // false

System.out.println(value1.compareTo(value2) == 0);// true

Wird für den Schlüssel von "HashMap" verwendet

BigDecimal # equals BigDecimal # hashCode berücksichtigt also auch scale Das Schreiben eines Systems, an dem Sie nicht interessiert sind, wie z. B. "Skala", kann Sie verletzen.

BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2

Map<BigDecimal, String> map = new HashMap<>();
map.put(value1, "data");

System.out.println(map.get(value2));// null

In diesem Fall möchten Sie möglicherweise die Skalierung mit BigDecimal # stripTrailingZeros stabilisieren.

BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2

Map<BigDecimal, String> map = new HashMap<>();
map.put(value1.stripTrailingZeros(), "data");

System.out.println(map.get(value2.stripTrailingZeros()));// data

RoundingMode

"RoundingMode" wird durch "enum" definiert, und neben "Rundung" gibt es verschiedene Dinge wie "Aufrunden", "Abschneiden", "Runden auf positive Unendlichkeit", "Runden auf negative Unendlichkeit", also einmal javadoc. Ich denke du solltest es überprüfen.

Das Folgende ist eine Transkription von Rounding Mode javadoc.

CEILING Es ist ein Modus zum Rollen, um sich der positiven Unendlichkeit zu nähern. DOWN Dieser Modus rundet auf 0 ab. FLOOR Es ist ein Modus zum Rollen, um sich der negativen Unendlichkeit zu nähern. HALF_DOWN Dies ist ein Rundungsmodus, der auf die "nächste Zahl" rundet (wenn die Zahlen auf beiden Seiten gleich weit entfernt sind, werden sie abgeschnitten). HALF_EVEN Rundungsmodus zum Runden auf die "nächstgelegene Zahl" (wenn jedoch die Zahlen auf beiden Seiten gleiche Abstände haben, auf die gerade Seite runden). HALF_UP Dies ist ein Rundungsmodus, der auf die "nächste Zahl" rundet (wenn jedoch die Zahlen auf beiden Seiten gleich weit entfernt sind, werden sie aufgerundet). UNNECESSARY Ein Rundungsmodus, der anzeigt, dass das Ergebnis der erforderlichen Operation genau ist und keine Rundung erfordert. UP Dieser Modus rundet von 0 ab.

Methoden, die durch "RoundingMode" ersetzt werden können, sind nicht verfügbar

Verwenden Sie nicht das BigDecimal # ROUND_ ~ -System und die Methoden, die deren Verwendung voraussetzen. (@ Veraltet in Java 9) Es sollte zwei Methoden geben, die für jede Methode "RoundingMode" verwenden. Verwenden wir also diese.

Die Methode, die in 9 zu "@ Deprecated" wurde, ist ein Erbe der 1.4-Ära. Wenn ich jedoch normalerweise mit "BigDecimal Division" google, bin ich verzweifelt, weil alle Seiten, die "BigDecimal.ROUND_HALF_UP" verwenden, herauskommen.

Recommended Posts

[Java] Big Decimal richtig verwenden ~ 2018 ~
Java Big Decimal
Wie man Big Decimal benutzt
[Java] Verwenden Sie Collectors.collectingAndThen
[Ruby] Big Decimal und DECIMAL
Große Dezimalstelle in Kotlin
Verwenden Sie OpenCV mit Java
Verwenden Sie PreparedStatement in Java
[java] Nummer ablehnen → Zahl n-Zahl → Dezimalzahl
Verwendung von Abstract Class und Interface in Java richtig
Verwenden Sie Lambda-Ebenen mit Java
Verwendung von Java Optional
Verwendung der Java-Klasse
[Java] Verwendung von removeAll ()
Verwendung von Java Map
[Java] Gründe für die Verwendung von statischen
Verwendung von Java-Variablen
CICS-Java-Anwendung ausführen- (5) Verwenden Sie JCICSX
Verwenden Sie SpatiaLite mit Java / JDBC
Verwendung von HttpClient (Get) von Java
Verwenden Sie Java mit MSYS und Cygwin
Verwenden Sie Microsoft Graph mit Standard-Java
Verwendung von HttpClient (Post) von Java
[Java] Verwendung der Join-Methode
Verwenden wir Twilio in Java! (Einführung)
Verwenden Sie Azure Bing SpellCheck mit Java
Verwenden Sie JDBC mit Java und Scala.
[Java] Verwenden Sie nicht "+" im Anhang!
Verwenden Sie zusammengesetzte Schlüssel in Java Maps.
Verwenden Sie Java 11 mit Google Cloud-Funktionen
Java (Klassentyp für Feld verwenden)
Verwenden Sie Chrome Headless von Selenium / Java
[JavaFX] [Java8] Verwendung von GridPane
[Hinweis] Behandlung von Java-Dezimalstellen
Verwendung von Klassenmethoden [Java]
[Java] Verwendung von List [ArrayList]
Wie verwende ich Klassen in Java?
[Verarbeitung × Java] Verwendung von Arrays
Verwendung von Java-Lambda-Ausdrücken
Verwenden Sie Stream in Java?
[Java] Verwendung der Math-Klasse
Verwendung des Java-Aufzählungstyps
[Java] Tipps und Fehlerprobleme beim Konvertieren von Double zu Big Decimal
Verhindern Sie, dass die Exponenten-Notation (E) angezeigt wird, wenn toString von Javas Big Decimal ausgeführt wird