Wie man Dezimalstellen in Java abschneidet (int-Cast, Math.floor, BigDecimal setScale)

目次

1. Was bedeutet „Dezimalstellen abschneiden“ in Java?

Wenn Leute in Java von „Dezimalstellen abschneiden“ sprechen, meinen sie normalerweise entweder das Entfernen des Bruchteils, um eine ganze Zahl zu erhalten oder das Weglassen von Ziffern nach der n‑ten Dezimalstelle.
Im realen Code kann „abschneiden“ jedoch mehr als eine Bedeutung haben, also klären wir zunächst das Fazit.

1.1 Bedeutet „truncate“ floor? Oder cast? (Terminologie)

Es gibt im Wesentlichen zwei Muster des „Abschneidens“.

  • (A) Abschneiden Richtung 0 (truncate) – Entfernt den Bruchteil, aber bei negativen Zahlen bewegt es sich „näher an Null“. Beispiele: 3.9 → 3, -3.9 → -3 → In Java verhält sich (int)-Casting so.
  • (B) Abschneiden Richtung −∞ (floor) – Bewegt sich nach unten (zu kleineren Werten) auf der Zahlenlinie. Beispiele: 3.9 → 3, -3.9 → -4 → In Java verhält sich Math.floor() so.

Anfänger verwechseln das häufig, weil bei positiven Zahlen (A) und (B) das gleiche Ergebnis liefern.
Aber sobald man negative Zahlen behandelt, divergieren die Ergebnisse.

1.2 Was dieser Artikel Ihnen ermöglicht (schnellster Weg nach Anwendungsfall)

Personen, die nach „java truncate decimals“ suchen, wollen in der Regel eines der Folgenden:

  • Einfach in eine ganze Zahl konvertieren (z. B. 3.14 → 3) → Casting mit (int) ist am schnellsten. Aber seien Sie vorsichtig bei negativen Zahlen.
  • Auf 2 Dezimalstellen abschneiden (z. B. 1.239 → 1.23) → Math.floor(x * 100) / 100 kann funktionieren → Aber wenn Präzision wichtig ist, ist BigDecimal sicherer.
  • Geld-/Abrechnungs‑/Tarifwerte, bei denen Fehler inakzeptabel sind → Verwenden Sie BigDecimal + setScale + RoundingMode.

Wählen Sie die falsche Methode, wirkt sie oft „funktionierend“, bricht aber später zusammen.
Insbesondere können Berechnungen mit double Präzisionsfehler einführen, daher ist es bei geldbezogener Logik sicherer, von Anfang an mit BigDecimal zu arbeiten.

1.3 Häufige Stolperfallen (zuerst diese beheben)

Drei gängige Fehler sind:

  • Annahme, dass (int) immer floor bedeutet → Tatsächlich rundet es Richtung Null, sodass negative Zahlen abweichen.
  • Verwendung von Math.floor zum Abschneiden von Dezimalstellen, aber leichte Abweichungen erhalten → Oft verursacht durch double‑Präzision (abhängig von Werten/Umgebung).
  • Verwendung von Formatierung (DecimalFormat usw.) als ob sie den berechneten Wert ändert → Die Anzeige kann sich ändern, während der interne Wert gleich bleibt.

Zuerst den kürzesten Weg bestätigen: „Wenn Sie nur eine ganze Zahl benötigen, casten.“ Dann die „Negative‑Zahl‑Falle“ verstehen.

Im nächsten Abschnitt erklären wir Abschneiden mittels (int)-Casting mit konkreten Beispielen.

2. Wenn Sie nur ein int wollen, funktioniert Casting (aber es gibt einen Haken)

Wenn Sie nur den Bruchteil entfernen und ein ganzzahliges Ergebnis (int) erhalten wollen, ist der schnellste Ansatz in Java Casting (Typumwandlung).
Casting ist jedoch nicht „mathematisches Abschneiden (floor)“. Es ist Rundung Richtung Null (truncate), was erheblich sein kann.

2.1 Grundlagen: Abschneiden des Bruchteils mit (int)

Wenn Sie einen double oder float in int umwandeln, wird der Bruchteil verworfen.

double x = 3.99;
int a = (int) x;
System.out.println(a); // 3

Dies ist die einfachste Antwort für das häufige Anliegen „Ich möchte Dezimalstellen abschneiden“.

Die Schritte sind:

  • Bestätigen, dass der Wert ein double / float ist
  • (int) hinzufügen, um ihn zu int zu casten
  • Das Ergebnis überprüfen – einschließlich negativer Zahlen, falls diese auftreten können

2.2 Wichtig: Casting rundet Richtung Null (negative Zahlen unterscheiden sich)

Dies ist die #1‑Falle für Anfänger.
Casting „rundet“ nicht immer „nach unten“.

System.out.println((int) 3.9);   // 3
System.out.println((int) -3.9);  // -3

-3.9 wird zu -3 (nicht zu -4), weil das Casting in Richtung näher an Null konvertiert.

  • 3.9 → 3 (nach Null)
  • -3.9 → -3 (nach Null)

Wenn Sie „mathematisches Abschneiden (floor)“ wollen, benötigen Sie Math.floor(), nicht Casting.
Verpassen Sie das, können Sie Bugs in Bereichen wie Gewinn‑/Verlust‑Berechnungen, Gebührenberechnungen oder Koordinatenmathematik erhalten, wo nur die negative Seite falsch ist.

2.3 Häufige Fehler: Annahme von Rundung / Probleme bei Negativen

Casting ist keine Rundung zum nächsten Wert.
Wenn Sie denken, dass „0,9 zu 1 wird“, liegen Sie falsch.

System.out.println((int) 0.9);  // 0
System.out.println((int) 1.9);  // 1

Auch bei negativen Zahlen kann es so wirken, als ob der Wert unerwartet „zugenommen“ oder „abgenommen“ hat.

  • -3.9 → -3 bewegt sich in die größere Richtung auf der Zahlenlinie
  • Wenn Sie -4 erwartet haben, ist das ein echter Fehler

Lösung ist einfach:

  • Wenn Sie nur positive Werte verarbeiten → Casting ist in Ordnung
  • Wenn negative Werte auftreten können → erwägen Sie Math.floor()
  • Wenn strenge Präzision erforderlich ist (Geld usw.) → erwägen Sie BigDecimal

Im nächsten Abschnitt erklären wir Math.floor() / Math.ceil(), die es ermöglichen, auch bei negativen Zahlen mathematisch konsistent zu truncaten.

3. Verwenden Sie Math.floor / Math.ceil für korrektes Dezimaltruncaten

Wenn Sie Dezimalzahlen mathematisch korrekt truncaten möchten, ist der grundlegende Ansatz, Math.floor() anstelle von Casting zu verwenden.
Insbesondere wenn negative Zahlen auftreten können, reduziert die bloße Wahl von Math.floor() Bugs erheblich.

3.1 Truncation mit Math.floor() (Floor‑Funktion)

Math.floor() wird als Floor‑Funktion bezeichnet und rundet Werte nach unten (zu kleineren Werten) auf der Zahlenlinie.

System.out.println(Math.floor(3.9));   // 3.0
System.out.println(Math.floor(-3.9));  // -4.0

Wichtige Punkte:

  • 3.9 → 3.0 (nach unten bewegt)
  • -3.9 → -4.0 (weiter nach unten bewegt)

Der größte Vorteil ist, dass Truncation bei negativen Zahlen nicht unerwartet verhält.

Eine häufige Falle ist, dass Math.floor() einen double zurückgibt.
Wenn Sie einen Integer benötigen, müssen Sie ihn anschließend konvertieren.

3.2 Math.ceil() rundet auf — Verwechseln Sie es nicht

Math.ceil() ist das Gegenstück zu Math.floor() und rundet nach oben (zu größeren Werten) auf der Zahlenlinie.

System.out.println(Math.ceil(3.1));   // 4.0
System.out.println(Math.ceil(-3.1));  // -3.0

Ein häufiger Fehler ist:

  • Zu denken, dass „Dezimalstellen entfernen“ ceil bedeutet → In Wirklichkeit rundet ceil nach oben, was oft das Gegenteil dessen ist, was Sie wollen.

Wenn Sie nach „Dezimalstellen truncaten“ gesucht haben, ist floor in der Regel die richtige Wahl.

3.3 Typumwandlung beim Konvertieren zu long / int

Wenn Sie das Ergebnis von Math.floor() zu int oder long konvertieren möchten, müssen Sie es casten.

double x = -3.9;

int a = (int) Math.floor(x);
System.out.println(a); // -4

Zu beachtende Punkte:

  • Das Ergebnis von Math.floor() ist ein double
  • Das Casten zu int entfernt den Dezimalteil (keine Unstimmigkeit in diesem Schritt)
  • Wenn der Wert zu groß ist, passt er möglicherweise nicht in einen int

Zur Sicherheit können Sie zuerst long wählen.

double x = 12345678901.9;

long b = (long) Math.floor(x);
System.out.println(b); // 12345678901

Häufige Fehler umfassen:

  • Vergessen zu casten und den Wert als double zu belassen
  • Den Unterschied zwischen floor und casting nicht verstehen, was zu Bugs bei negativen Zahlen führt
  • Overflow, wenn der Wertebereich von int überschritten wird

Kurz gesagt, wenn negative Zahlen auftreten können, ist es am sichersten, von Anfang an um Math.floor() herum zu designen.

Im nächsten Abschnitt erklären wir, wie man am n‑ten Dezimalplatz truncatet (z. B. zwei Dezimalstellen beibehält) mit konkreten Beispielen.

4. Wie man am n‑ten Dezimalplatz truncatet (häufig in Anzeige & Berechnungen)

In realen Anwendungen ist es sehr üblich, bis zu einer bestimmten Dezimalstelle zu behalten und den Rest zu verwerfen, nicht nur alle Dezimalstellen zu entfernen.
Beispiele sind Steuersätze, Wechselkurse, Stückpreise und Prozentsätze.

Hier stellen wir praktische Methoden zum Truncaten am n‑ten Dezimalplatz vor.
Bei Verwendung von double können Präzisionsprobleme auftreten, daher behandeln wir auch die Fallstricke.

4.1 Grundmuster: Mit 10^n multiplizieren, floor, dann teilen

  1. Bestimmen Sie die Anzahl der Dezimalstellen n
  2. Multiplizieren Sie mit 10^n
  3. Wenden Sie Math.floor() an
  4. Teilen Sie durch 10^n, um die Skala wiederherzustellen

Für das Abschneiden auf 2 Dezimalstellen (z. B. 1.239 → 1.23):

double x = 1.239;
double y = Math.floor(x * 100) / 100;
System.out.println(y); // 1.23

Für das Abschneiden auf 3 Dezimalstellen (z. B. 1.2399 → 1.239):

double x = 1.2399;
double y = Math.floor(x * 1000) / 1000;
System.out.println(y); // 1.239

Vorteile dieses Ansatzes:

  • Kurzer und einfacher Code
  • Verwendet Math.floor(), sodass das Verhalten bei negativen Zahlen konsistent ist
  • Keine zusätzlichen Bibliotheken erforderlich

Allerdings basiert dies auf double und ist nicht für präzise Berechnungen wie Geldbeträge geeignet.

4.2 Fallstrick: Unerwartete Ergebnisse aufgrund von double‑Präzision

Javas double ist ein Gleitkomma‑Typ und kann Werte wie 0,1 oder 0,01 nicht immer exakt darstellen.
Infolgedessen können scheinbar „unsinnige“ Abweichungen auftreten (abhängig von den Werten und der Umgebung).

  • Sie erwarten 1.29, erhalten aber 1.28
  • Sie verarbeiten 0.3, intern ist es jedoch 0.299999999...

Zum Beispiel sieht der folgende Code logisch korrekt aus:

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

Intern kann x * 100 jedoch als 128.999999999... dargestellt werden.
Wenn floor 128 zurückgibt, wird das Ergebnis 1,28.
Das ist kein Fehler in Java, sondern eine Eigenschaft der Gleitkommaarithmetik.

Der knifflige Teil ist, dass dies nur gelegentlich passiert, was das Aufspüren während des Testens erschwert.

4.3 Sicheres Abschneiden mit BigDecimal (empfohlen)

Wenn Sie an der n‑ten Dezimalstelle zuverlässig abschneiden möchten, ist die Verwendung von BigDecimal die sicherste Wahl.
BigDecimal verarbeitet Dezimalzahlen exakt und wird häufig für Geldberechnungen verwendet.

Das Grundmuster lautet:

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // truncate at 2 decimal places
System.out.println(y); // 1.23

Wichtige Punkte:

  • setScale(2, ...) behält zwei Dezimalstellen bei
  • RoundingMode.DOWN gibt das Abschneiden Richtung Null an

Beachten Sie, dass das DOWN von BigDecimal nicht dasselbe ist wie Math.floor().
Bei negativen Zahlen unterscheidet sich das Verhalten, sodass Sie möglicherweise auch FLOOR berücksichtigen müssen (später erklärt).

Häufige Fehler umfassen:

  • Erstellen eines BigDecimal aus einem double (Einführen von Präzisionsfehlern)
  • Vergessen, setScale aufzurufen
  • Verwendung des falschen Rundungsmodus und versehentliches Runden nach oben (half‑up)

Zusammenfassend kann Math.floor für reine Anzeigezwecke ausreichend sein, aber für wichtige Berechnungen ist BigDecimal die sicherste Wahl.

Im nächsten Abschnitt gehen wir tiefer auf das Abschneiden mit BigDecimal ein, einschließlich der korrekten Art, Instanzen zu erstellen für den realen Code.

5. Abschneiden mit BigDecimal (am sichersten für Finanzen, Abrechnung und Tarife)

Wenn Sie Dezimalzahlen mit maximaler Genauigkeit abschneiden möchten, sollte BigDecimal Ihre erste Wahl in Java sein.
double ist schnell, aber anfällig für Präzisionsfehler, die später bei Geld-, Abrechnungs‑, Gebühren‑ oder Tarifberechnungen Probleme verursachen können.
BigDecimal verarbeitet Dezimalzahlen auf eine Weise, die den menschlichen Erwartungen näher kommt, weshalb es im geschäftlichen Code weit verbreitet ist.

5.1 BigDecimal‑Grundlagen: Erstellung aus double ist gefährlich (am wichtigsten)

Ein sehr häufiger Fehler bei BigDecimal ist wie es erstellt wird.
Wenn Sie ein double direkt übergeben, kann der interne Präzisionsfehler erhalten bleiben.

import java.math.BigDecimal;

BigDecimal a = new BigDecimal(0.1);
System.out.println(a); // May become something like 0.10000000000000000555...

Das Abschneiden oder Berechnen mit diesem Wert führt häufig zu „mysteriösen“ Abweichungen.

Sichere Wege, BigDecimal zu erstellen, sind:

(A) Aus einem String erstellen (am explizitesten und sichersten)

BigDecimal a = new BigDecimal("0.1");

(B) BigDecimal.valueOf(double) verwenden (oft empfohlen)

BigDecimal a = BigDecimal.valueOf(0.1);

Für Anfänger ist die sicherste Regel: Wenn Sie unsicher sind, erstellen Sie BigDecimal aus einem String.

5.2 Abschneiden an n Dezimalstellen mit RoundingMode.DOWN

Um an der n-ten Dezimalstelle abzuschneiden, verwenden Sie setScale.

  • setScale(2, ...) → zwei Dezimalstellen beibehalten
  • RoundingMode.DOWN → Abschneiden in Richtung Null
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    
    BigDecimal x = new BigDecimal("123.4567");
    BigDecimal y = x.setScale(2, RoundingMode.DOWN);
    
    System.out.println(y); // 123.45
    

Wenn Sie alle Dezimalstellen entfernen und einen ganzzahligen Wert erhalten möchten, gilt der gleiche Ansatz.

BigDecimal x = new BigDecimal("123.999");
BigDecimal y = x.setScale(0, RoundingMode.DOWN);

System.out.println(y); // 123

Ein wichtiger Hinweis: setScale ändert den Wert selbst, nicht nur die Anzeige.
Dies ist eine Rechenoperation, keine Formatierung.

5.3 Abschneiden in Richtung Null vs. Floor-Richtung (Wichtiger Unterschied)

BigDecimal bietet mehrere Rundungsmodi, und es gibt zwei, die wie „Abschneiden“ wirken und verwirrend sein können.

  • RoundingMode.DOWN : Abschneiden in Richtung Null

    • 3.9 → 3
    • -3.9 → -3
    • RoundingMode.FLOOR : Abschneiden in Richtung −∞ (mathematische Floor-Funktion)

    • 3.9 → 3
    • -3.9 → -4

Wenn Sie möchten, dass Werte immer in Richtung der kleineren Seite auf der Zahlengeraden verschoben werden, ist FLOOR die richtige Wahl.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x1 = new BigDecimal("-3.9");
System.out.println(x1.setScale(0, RoundingMode.DOWN));  // -3
System.out.println(x1.setScale(0, RoundingMode.FLOOR)); // -4

Welcher „korrekt“ ist, hängt vollständig von Ihrem Anwendungsfall ab.

  • Einfaches Entfernen von Ziffern (Abschneiden) → DOWN
  • Mathematisches Abschneiden (Floor) → FLOOR

Wenn dieser Unterschied unklar ist, können negative Werte zu schweren Spezifikationsfehlern führen.

5.4 Häufige BigDecimal-Fehler

Hier sind häufige Fehler beim Abschneiden mit BigDecimal:

  • Erstellen von BigDecimal aus double und Einführen von Präzisionsfehlern → Vermeiden Sie new BigDecimal(0.1) ; verwenden Sie String oder valueOf
  • Verwendung der falschen Skala → Zum Beispiel 0 statt 2 Dezimalstellen
  • Verwechslung von Rundungsmodi → Verwechslung von DOWN und FLOOR, was zu Problemen bei negativen Zahlen führt
  • Ändern von Werten, wenn Sie nur formatieren wolltensetScale ändert den Wert; trennen Sie Berechnung und Anzeige

Kurz gesagt, für Geld, Abrechnung oder Raten – wo selbst ein Cent-Unterschied zählt –
verwenden Sie BigDecimal und korrigieren Sie sowohl die Erstellungsweise als auch den Rundungsmodus.

Im nächsten Abschnitt erklären wir, wie Sie die Verwechslung von Anzeigeformatierung und Berechnungsabschneiden vermeiden.

6. DecimalFormat / String.format sind nur für die Anzeige (Nicht für Berechnungen verwenden)

Beim Abschneiden von Dezimalzahlen ist es entscheidend zu unterscheiden, ob Sie den berechneten Wert abschneiden oder nur die Anzeige formatieren möchten.
Die Verwechslung dieser beiden führt zu Situationen, in denen die Anzeige korrekt aussieht, aber der interne Wert falsch ist, was später zu Fehlern führt.

Der wichtigste Tipp: DecimalFormat und String.format sind nur für die Anzeige.
Wenn Sie den tatsächlichen Wert abschneiden müssen, verwenden Sie BigDecimal oder Math.floor().

6.1 Formatieren von Dezimalstellen mit DecimalFormat (Abschneiden möglich)

DecimalFormat ist eine Klasse zur Umwandlung von Zahlen in formatierte Strings.
Zum Beispiel wird sie oft verwendet, wenn Sie zwei Dezimalstellen anzeigen möchten.

import java.text.DecimalFormat;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(x)); // May become 1.24 (rounded)

Wichtig ist, dass der Rückgabewert von format() ein String ist,
und der numerische Wert von x selbst sich nicht ändert.

Sie können auch den Rundungsmodus angeben.
Um die Anzeige abzuschneiden, gehen Sie wie folgt vor:

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // 1.23

However, this only changes the displayed string; the value of x remains unchanged.

6.2 Caveats When Using String.format

String.format also lets you control numeric output formatting.

double x = 1.239;
System.out.println(String.format("%.2f", x)); // Often rounds to 1.24

In many cases, String.format("%.2f", x) performs round half up behavior.
It’s usually unsuitable if you specifically want truncation.

A very common beginner mistake is converting a formatted string back into a number and using it in calculations.

double x = 1.239;
String s = String.format("%.2f", x); // "1.24"
double y = Double.parseDouble(s);    // 1.24

// At this point, calculations use a rounded value, not a truncated one

This mixes display concerns into calculation logic, making future changes harder.

6.3 Key Pitfall: Correct Display Does Not Mean Correct Values

The most dangerous assumption is “it looks correct on the screen, so it must be fine.”

  • DecimalFormat / String.format change how values look
  • Math.floor / BigDecimal.setScale change the actual value

If you confuse these, you may run into problems like:

  • The UI shows “$1.23” but internal calculations still sum “$1.239”
  • Rounding happens at the wrong stage, causing billing totals to differ
  • Display rounding leaks into calculations, causing audit discrepancies

A simple rule of thumb:

  • Only formatting for display → DecimalFormat (or UI formatting)
  • Truncating as part of calculation → BigDecimal / Math.floor

In the next section, we’ll provide a quick reference table so you can instantly choose the right approach by use case.

7. Best Practices by Use Case (Quick Reference)

“Java decimal truncation” is confusing because there are multiple valid approaches.
Here, we fix the decision by mapping use case → best solution, so you can choose quickly.

7.1 Convert to int (Positive Numbers Only) → Casting Is Enough

If you just want to remove decimals and convert to int, and negative numbers will never appear, casting is the fastest option.

double x = 12.99;
int y = (int) x;
System.out.println(y); // 12

Things to remember:

  • Casting rounds toward zero
  • With positive values, it looks the same as truncation
  • If negatives may appear, don’t lock in this approach

7.2 Truncate Including Negative Numbers → Math.floor

If you want mathematical truncation (floor), Math.floor() is the correct choice.
It’s safer than casting when negative numbers may occur.

double x = -3.9;
int y = (int) Math.floor(x);
System.out.println(y); // -4

Common notes:

  • Math.floor() returns a double
  • Cast to int or long if needed
  • Watch out for int overflow with large values

7.3 Truncate at the n-th Decimal Place (Strict) → BigDecimal + setScale

If you want to truncate at a specific decimal place without precision errors, BigDecimal is the safest option.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN);

System.out.println(y); // 1.23

This approach is ideal for:

  • Money (JPY, USD, etc.)
  • Billing and tax calculations
  • Rate calculations where errors are unacceptable
  • Batch jobs requiring deterministic results

Common pitfalls:

  • Do not create BigDecimal from double (avoid new BigDecimal(0.1) )
  • Understand the difference between DOWN and FLOOR (negative numbers)

7.4 Format for Display Only → DecimalFormat (Never for Calculation)

If you only want to format numbers for display (e.g., two decimals), DecimalFormat is convenient.
However, it does not change the underlying numeric value, so never use it for calculations.

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Hinweise:

  • Der Rückgabewert ist ein String
  • Das Vermischen von Anzeige‑Logik mit Berechnungen verursacht Fehler

In einem Satz lautet die Kernaussage:

  • Schnell & einfach → Casting
  • Korrekt bei Negativen → Math.floor
  • Genauigkeit zuerst (realwelt) → BigDecimal
  • Nur Anzeige → DecimalFormat

Als Nächstes fassen wir die häufigsten Fehler zusammen und zeigen, wie man sie vermeidet.

8. Häufige Fehler und wichtige Warnungen

Das Abschneiden von Dezimalstellen „scheint oft zu funktionieren“, wodurch Anfänger subtile Fehler leicht übersehen können.
Hier sind reale Fehler und wie man sie vermeidet.

8.1 Missverständnis der Bedeutung von „Truncate“ (Hin zu 0 vs. Floor)

Der häufigste Fehler ist die Annahme, dass Truncate immer „kleiner werden“ bedeutet.
In Java hängt die Bedeutung von der verwendeten Methode ab.

  • Casting (int) : in Richtung Null

    • 3.9 → 3
    • -3.9 → -3
    • Math.floor() : in Richtung −∞

    • 3.9 → 3
    • -3.9 → -4

Wenn negative Werte möglich sind und Sie Casting verwenden, ist nur die negative Seite falsch.
Das bleibt oft unbemerkt, wenn Tests nur positive Werte verwenden.

Gegenmaßnahmen:

  • Wenn negative Werte auftreten können, sollten Sie von Anfang an Math.floor() in Betracht ziehen
  • Bei BigDecimal nicht RoundingMode.DOWN und FLOOR verwechseln

8.2 Unerwartete Ergebnisse aufgrund von double‑Präzision

Bei der Implementierung von Truncation mit Math.floor(x * 100) / 100 können Sie trotz korrekter Logik Ungereimtheiten feststellen.
Die Ursache liegt in der internen Darstellung von double.

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

Abhängig vom Wert kann x * 100 zu 128.999999999... werden, was zu 1.28 führt.
Da dies nicht jedes Mal passiert, wird es häufig erst in der Produktion entdeckt.

Gegenmaßnahmen:

  • Verwenden Sie BigDecimal für Geld‑ und Abrechnungszwecke
  • Wenn Sie double verwenden, beschränken Sie den Einsatz auf Fälle, in denen kleine Fehler tolerierbar sind

8.3 Verwendung von double für Geldberechnungen

Die Verwendung von double für Geld führt häufig zu:

  • Summen stimmen nach Truncation nicht überein
  • Kleine Rundungsfehler summieren sich
  • Diskrepanz zwischen angezeigten und internen Werten

Gegenmaßnahmen:

  • Verwenden Sie BigDecimal für Geldwerte
  • Korrigieren Sie die Erzeugungsmethode (String oder valueOf)
  • Dokumentieren Sie Rundungsregeln explizit

8.4 Verwendung von Anzeigeformatierung für Berechnungen

Die Formatierung mit DecimalFormat oder String.format und anschließendes Zurückparsen in Zahlen ist gefährlich.

double x = 1.239;
String s = String.format("%.2f", x); // display formatting
double y = Double.parseDouble(s);    // used in calculation (dangerous)

Dies führt zu:

  • Rundungsfehler aus der Anzeige fließen in Berechnungen ein
  • Änderungen der Spezifikation beeinflussen die Logik
  • Verlust der Trennung zwischen Anzeige und Berechnung

Gegenmaßnahmen:

  • Schließen Sie Berechnungen mit BigDecimal oder Math.floor() ab
  • Formatieren Sie nur in der finalen Anzeigephase
  • Halten Sie Berechnung und Darstellung getrennt

9. Zusammenfassung: Copy‑Paste‑Schlussfolgerungen

Es gibt mehrere Möglichkeiten, Dezimalstellen in Java zu truncaten, aber der schnellste Weg ist, nach Anwendungsfall zu wählen.
Hier sind gebrauchsfertige Schlussfolgerungen.

9.1 Wenn Sie unsicher sind, verwenden Sie diese

Fall 1: In int konvertieren (nur positive Zahlen)

double x = 12.99;
int y = (int) x;  // 12

Hinweis: Bei negativen Zahlen ergibt -3.9 → -3, also ist dies kein mathematischer Floor.

Fall 2: Mathematisches Truncaten inklusive negativer Werte

double x = -3.9;
int y = (int) Math.floor(x); // -4

Hinweis: Math.floor() trunciert in Richtung −∞.

Fall 3: Truncate auf n Dezimalstellen (double, einfach)

*Nur verwenden, wenn kleine Präzisionsfehler tolerierbar sind.

double x = 1.239;
double y = Math.floor(x * 100) / 100; // 1.23

Warnung: double‑Präzisionsprobleme können auftreten. Für strenge Genauigkeit verwenden Sie BigDecimal.

Fall 4: Zuverlässig auf n Dezimalstellen kürzen (empfohlen)

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // 1.23

Wichtige Punkte:

  • Erstellen Sie kein BigDecimal aus einem double
  • Verwenden Sie dies für Geld, Abrechnungen und Tarife

Fall 5: Nur Anzeige (niemals für Berechnungen)

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Hinweis: Dies erzeugt einen String; der numerische Wert bleibt unverändert.

FAQ

Q1. Was ist der einfachste Weg, Dezimalzahlen in Java zu kürzen?

Antwort: Wenn Sie nur einen ganzzahligen Wert benötigen, ist das Casten mit (int) am schnellsten. Falls negative Zahlen auftreten können, sollten Sie Math.floor() in Betracht ziehen.

Q2. Warum liefert (int) bei negativen Zahlen unerwartete Ergebnisse?

Antwort: Ein Cast rundet Richtung Null. Zum Beispiel -3.9 → -3. Für mathematisches Kürzen verwenden Sie Math.floor().

Q3. Wie kann ich auf zwei Dezimalstellen kürzen (z. B. 1.239 → 1.23)?

Antwort: Für einen einfachen Ansatz verwenden Sie Math.floor(x * 100) / 100. Für strenge Genauigkeit nutzen Sie BigDecimal.setScale(2, RoundingMode.DOWN).

Q4. Warum liefert Math.floor(x * 100) / 100 manchmal falsche Werte?

Antwort: Das liegt an Präzisionsfehlern von double. Für Geldbeträge oder Abrechnungen sollten Sie zu BigDecimal wechseln.

Q5. Wie ist der korrekte Weg, mit BigDecimal zu kürzen?

Antwort: Erzeugen Sie ein BigDecimal aus einem String oder mit valueOf, und verwenden Sie dann setScale(n, RoundingMode.DOWN). Vermeiden Sie new BigDecimal(double).

Q6. Was ist der Unterschied zwischen RoundingMode.DOWN und FLOOR?

Antwort: Sie unterscheiden sich bei negativen Zahlen. DOWN kürzt Richtung Null; FLOOR kürzt Richtung −∞. Wählen Sie je nach gewünschtem Verhalten, ob Sie kürzen oder mathematisch abrunden wollen.

Q7. Kann ich Dezimalzahlen mit DecimalFormat kürzen?

Antwort: Sie können die Anzeige durch Setzen eines Rundungsmodus kürzen, aber das betrifft nur die Darstellung. Der interne Wert bleibt unverändert.

Q8. Wann sollte das Kürzen in Berechnungen angewendet werden?

Antwort: Das hängt von der Spezifikation ab. Entscheiden Sie, ob Sie pro Schritt oder am Ende kürzen, dokumentieren Sie die Regel eindeutig und setzen Sie sie konsequent um – vorzugsweise mit BigDecimal.