2011-01-04 14 views

Antwort

647

Aus dem Java 5 docs (Java 8 docs here):

Wenn ein MathContext Objekt mit einer Genauigkeit Einstellung von 0 (für Beispiel geliefert wird, MathContext.UNLIMITED), arithmetische Operationen sind genau, da die arithmetischen Methoden sind, die kein MathContext-Objekt verwenden. (Dies ist das einzige Verhalten, das vor dem 5. in Versionen unterstützt wurde)

Als logische Folge des genaue Ergebnisses der Berechnung, die Rundungsmoduseinstellung eines MathContext Objekt mit einer Genauigkeit der Einstellung 0 wird nicht verwendet, und somit irrelevant. In der Fall der Division, könnte der genaue Quotient eine unendlich lange Dezimal Expansion haben; Beispiel: 1 dividiert durch 3.

Wenn der Quotient eine nicht abschließende Dezimal-Erweiterung hat und die Operation angegeben wird, um ein genaues Ergebnis zurückzugeben, wird eine ArithmeticException ausgelöst. Andernfalls wird das genaue Ergebnis der Division zurückgegeben, wie für andere Operationen getan.

Um dies zu beheben, müssen Sie so etwas wie dieses 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/

+2

geschnitten werden Ich glaube nicht, dass er die 'toPlainString' braucht. –

+2

das funktioniert für Jaspis Fehler auch danke http://community.jaspersoft.com/questions/528968/help-please-adding-two-double-values#comment-807628 – shareef

+15

2 ist nicht 'Präzision'; Es ist "Maßstab". Siehe http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divide%28java.math.BigDecimal,%20int,%20java.math.RoundingMode%29 –

68

Da Sie eine Präzision und ein Rundungsmodus spezifiziert sind nicht. BigDecimal beschweren 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 dir ein falsches BigDecimal zu geben, winkt es dir nur zu.

Wenn Sie jedoch einen RoundingMode und eine Genauigkeit liefern, dann wird es in der Lage sein, (zB 1.333333333 zu Unendlich zu etwas wie 1.3333 zu konvertieren ... aber Sie als der Programmierer müssen ihm sagen, welche Genauigkeit Sie ' re 'zufrieden'.

5

ich das gleiche Problem hatte, weil meine Codezeile war:

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

ich dies zu ändern, vorherige Antwort zu lesen, weil ich keine Dezimalgenauigkeit:

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

4 Dezimal Precion

UND RoundingMode sind Enum-Konstanten können Sie eines dieser UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

In diesem Fall HALF_UP, wird dieses Ergebnis haben wählen könnte:

2.4 = 2 
2.5 = 3 
2.7 = 3 

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

10

Zur Behebung eines solchen Problems habe ich unten den Code

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

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

+3

zusätzlich Zu dem Code sollte eine Erläuterung angegeben werden. –

+6

2 ist NICHT 'Präzision'; Es ist "Maßstab". Siehe http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divide%28java.math.BigDecimal,%20int,%20java.math.RoundingMode%29 –

+1

RoundingMode. HALF_EVEN wird für Finanzanwendungen empfohlen. Dies ist, was im Bankwesen verwendet wird – ACV

1

Antwort für BigDecimal throws ArithmeticException

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"))); 
    } 

hinzufügen MathContext Objekt in Ihrem divide Methodenaufruf und stellt Präzision und Rundungsmodus. Dies sollte Ihr Problem beheben

0

Es ist, weil die Bigdecimal hat nicht verloren, und wenn Sie 1/3 zum Beispiel teilen, wird es in einer wiederholten Dezimalzahl zu Unendlichkeit führen. 0.33333333 ... theoretisch, wenn Sie wieder multiplizieren, erhalten Sie das genaue Ergebnis. Aber eine Unendlichkeitszahl generiert Stapelüberlauf 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 Ihr Ergebnis wird nicht durch Rundung

+2

Dies ist ein 'Gambiara'. Bitte verwenden Sie die Lösung mit RoundingMode. –