638 Stimmen

ArithmeticException: "Nicht terminierende Dezimalentwicklung; kein exakt darstellbares dezimales Ergebnis"

Warum löst der folgende Code die unten gezeigte Ausnahme aus?

BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.

Eine Ausnahme:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

1032voto

DVK Punkte 123218

Von der Java 11 BigDecimal docs :

Wenn ein MathContext Objekt wird mit einer Präzisionseinstellung von 0 geliefert (zum Beispiel, MathContext.UNLIMITED ), sind die arithmetischen Operationen exakt, ebenso wie die arithmetischen Methoden, die keine MathContext Objekt. (Dies ist das einzige Verhalten, das in Versionen vor 5 unterstützt wurde).

Aus der Berechnung des exakten Ergebnisses ergibt sich, dass die Rundungsmoduseinstellung von a MathContext Objekt mit einer Präzisionseinstellung von 0 wird nicht verwendet und ist daher irrelevant. Im Falle von divide könnte der exakte Quotient eine unendlich lange dezimale Ausdehnung haben, zum Beispiel 1 geteilt durch 3.

Wenn der Quotient eine nicht endende dezimale Erweiterung hat und die Operation ein exaktes Ergebnis liefern soll, wird ein ArithmeticException geworfen wird. Andernfalls wird das genaue Ergebnis der Division zurückgegeben, wie bei anderen Operationen auch.

Um dies zu beheben, müssen Sie wie folgt vorgehen :

a.divide(b, 2, RoundingMode.HALF_UP)

wobei 2 die Skala und RoundingMode.HALF_UP der Rundungsmodus ist

Für weitere Einzelheiten siehe dieser Blogbeitrag .

94voto

David Bullock Punkte 5712

Denn Sie geben weder eine Genauigkeit noch einen Rundungsmodus an. BigDecimal beschwert sich darüber, dass es 10, 20, 5000 oder unendlich viele Nachkommastellen verwenden könnte und trotzdem nicht in der Lage wäre, eine exakte Darstellung der Zahl zu liefern. Anstatt Ihnen also eine falsche BigDecimal-Zahl zu liefern, meckert es Sie einfach an.

Wenn Sie jedoch einen RoundingMode und eine Genauigkeit angeben, kann das Programm z.B. 1.333333333-to-infinity in etwas wie 1.3333 konvertieren ... aber Sie als Programmierer müssen ihm sagen, mit welcher Genauigkeit Sie "zufrieden" sind.

80voto

MindBrain Punkte 6680

Das können Sie tun

a.divide(b, MathContext.DECIMAL128)

Sie können die Anzahl der gewünschten Bits wählen: entweder 32, 64 oder 128.

Sehen Sie sich diesen Link an:

http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext

24voto

Prahlad Punkte 197

Um ein solches Problem zu beheben, habe ich den folgenden Code verwendet

a.divide(b, 2, RoundingMode.HALF_EVEN)

Wobei 2 der Maßstab ist. Jetzt sollte das Problem gelöst sein.

7voto

Ich hatte das gleiche Problem, denn meine Codezeile war:

txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");

Ich ändere dies, wenn ich die vorherige Antwort lese, weil ich keine Dezimalpräzision geschrieben habe:

txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");

4 ist Dezimalpräzision

AND RoundingMode sind Enum-Konstanten, Sie können eine der folgenden Optionen wählen UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

In diesem Fall führt HALF_UP zu diesem Ergebnis:

2.4 = 2   
2.5 = 3   
2.7 = 3

Sie können die RoundingMode Informationen hier: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X