it-swarm.com.de

ArithmeticException: "Nicht endende dezimale Erweiterung; kein genau darstellbares Dezimalergebnis"

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.

-

Java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
440
Jason

Aus dem Java 8 docs: 

Wenn ein MathContext-Objekt mit einer Genauigkeitseinstellung von 0 geliefert wird (z. B. MathContext.UNLIMITED), sind arithmetische Operationen genau wie sind die arithmetischen Methoden, die kein MathContext-Objekt benötigen. (Dies ist das Verhalten von , Das in Releases vor Version 5 unterstützt wurde.) 

Als Folge der Berechnung des genauen Ergebnisses wird die Einstellung des Rundungsmodus eines MathContext Objekt mit einer Genauigkeit von 0 wird nicht verwendet und ist daher irrelevant. Im Im Fall der Division könnte der exakte Quotient eine unendlich lange Dezimalzahl haben. Erweiterung; Zum Beispiel: 1 geteilt durch 3. 

Wenn der Quotient eine nicht endende dezimale Erweiterung hat und Der Vorgang wird angegeben, um ein genaues Ergebnis zurückzugeben. Eine ArithmeticException wird ausgelöst. Andernfalls wird das genaue Ergebnis der Division zurückgegeben, wie für andere Operationen.

Um das Problem zu beheben, musst du Folgendes tun:

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

where 2 is precision and RoundingMode.HALF_UP is rounding mode

Weitere Details: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/

746
DVK

Weil Sie keine Genauigkeit und keinen Rundungsmodus angeben. BigDecimal beschwert sich, dass es 10, 20, 5000 oder unendlich Dezimalstellen verwenden könnte, und es wäre immer noch nicht in der Lage, Ihnen eine genaue Darstellung der Zahl zu geben. Anstatt Ihnen ein falsches BigDecimal-Zeichen zu geben, werden Sie nur angeschimpft.

Wenn Sie jedoch einen RoundingMode und eine Genauigkeit angeben, wird es in der Lage sein (z. B. 1.333333333-unendlich in etwas wie 1.3333) zu konvertieren, aber Sie als Programmierer müssen angeben, mit welcher Genauigkeit Sie zufrieden sind '.

71
David Bullock

Du kannst tun 

a.divide(b, MathContext.DECIMAL128)

Sie können die gewünschte Anzahl von Bits entweder 32,64,128 wählen.

Schauen Sie sich diesen Link an:

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

46
MindBrain

Zur Behebung eines solchen Problems habe ich den folgenden Code verwendet

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

2 ist Präzision. Nun wurde das Problem gelöst.

13
Prahlad

Ich hatte das gleiche Problem, weil meine Codezeile lautete:

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

Ich ändere dies und lese die vorherige Antwort, weil ich keine Dezimalgenauigkeit schrieb:

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

4 ist Dezimalzahl 

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

In diesem Fall hat HALF_UP folgendes Ergebnis:

2.4 = 2   
2.5 = 3   
2.7 = 3

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

6

Es ist eine Frage der Abrundung des Ergebnisses, die Lösung für mich ist folgende.

divider.divide(dividend,RoundingMode.HALF_UP);
1

Antwort auf BigDecimal löst ArithmeticException aus

public static void main(String[] args) {
        int age = 30;
        BigDecimal retireMentFund = new BigDecimal("10000.00");
        retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal yearsInRetirement = new BigDecimal("20.00");
        String name = " Dennis";
        for ( int i = age; i <=65; i++){
            recalculate(retireMentFund,new BigDecimal("0.10"));
        }
        BigDecimal monthlyPension =   retireMentFund.divide(
                yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));      
        System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
    }
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
        fundAmount.multiply(rate.add(new BigDecimal("1.00")));
    }

Fügen Sie Ihrem Divide-Methodenaufruf ein MathContext-Objekt hinzu und passen Sie die Genauigkeit und den Rundungsmodus an. Dies sollte Ihr Problem beheben

1
Poorna Chander

Dies liegt daran, dass der Bigdecimal-Wert nicht verloren geht. Wenn Sie beispielsweise 1/3 teilen, führt dies zu einer Wiederholung der Dezimalzahl bis unendlich. 0.33333333 ... Wenn Sie theoretisch zurück multiplizieren, erhalten Sie das genaue Ergebnis. Eine Unendlich-Zahl generiert jedoch einen Stack-Over-Flow, und in diesem Fall wird die Ausnahme gestartet. 

Meine Lösung:

 try {
     result = n1.divide(n2);
 } catch (ArithmeticException e){
     Log.d("Error bigdecimal", e.toString());
     result = (n1.doubleValue() / n2.doubleValue());
 };

in diesem Fall wird Ihr Ergebnis nicht durch Runden abgeschnitten

0
Leo Lima

Ihr Programm weiß nicht, mit welcher Genauigkeit Dezimalzahlen verwendet werden sollen, also wirft es aus:

Java.lang.ArithmeticException: Non-terminating decimal expansion

Lösung, um Ausnahme zu umgehen:

MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17
0
Miloš Ojdanić