Pourquoi le code suivant déclenche-t-il l'exception ci-dessous?
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.
Depuis le Java 8 docs:
Lorsqu'un objet MathContext est fourni avec un paramètre de précision de 0 (pour Exemple, MathContext.UNLIMITED), les opérations arithmétiques sont exactes, comme sont les méthodes arithmétiques qui ne prennent aucun objet MathContext. (Ceci est le seul comportement pris en charge dans les versions antérieures à la version 5.)
Corollaire du calcul du résultat exact, réglage du mode d'arrondi d'un MathContext objet avec un réglage de précision de 0 n'est pas utilisé et donc sans importance. Dans Dans le cas d'une division, le quotient exact pourrait avoir une décimale infiniment longue expansion; par exemple, 1 divisé par 3.
Si le quotient a une expansion décimale non-terminale et l'opération est spécifiée pour retourner un résultat exact, une exception ArithmeticException est levée . Autrement, le résultat exact de la division est renvoyé, comme indiqué pour autres opérations.
Pour résoudre ce problème, vous devez faire quelque chose comme ceci:
a.divide(b, 2, RoundingMode.HALF_UP)
where 2 is precision and RoundingMode.HALF_UP is rounding mode
Plus de détails: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/
Parce que vous ne spécifiez pas une précision et un mode d'arrondi. BigDecimal se plaint de pouvoir utiliser 10 décimales, 20 décimales, 5 000 décimales ou une infinité de décimales, sans pouvoir vous donner une représentation exacte du nombre. Donc, au lieu de vous donner un BigDecimal incorrect, cela vous blesse.
Cependant, si vous fournissez un RoundingMode et une précision, il sera alors capable de convertir (par exemple, 1,333333333-à-l'infini en quelque chose comme 1,3333 ... mais vous en tant que programmeur devez lui indiquer quelle précision vous êtes satisfait '.
Tu peux faire
a.divide(b, MathContext.DECIMAL128)
Vous pouvez choisir le nombre de bits que vous voulez soit 32,64,128.
Découvrez ce lien:
Pour résoudre un tel problème, j'ai utilisé le code ci-dessous
a.divide(b, 2, RoundingMode.HALF_EVEN)
2 est la précision. Maintenant le problème était résolu.
J'ai eu le même problème parce que ma ligne de code était:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
Je change en lisant la réponse précédente, car je n'écrivais pas de précision décimale:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4 est la précision décimale
ET RoundingMode sont des constantes Enum, vous pouvez choisir l'une de ces options UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP
Dans ce cas, HALF_UP, aura ce résultat:
2.4 = 2
2.5 = 3
2.7 = 3
Vous pouvez vérifier les informations RoundingMode
ici: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mound-enumeration/
C'est une question d'arrondir le résultat, la solution pour moi est la suivante.
divider.divide(dividend,RoundingMode.HALF_UP);
Réponse pour BigDecimal lève 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")));
}
Ajoutez un objet MathContext à votre appel à la méthode de division et ajustez le mode de précision et d'arrondissement. Cela devrait résoudre votre problème
C'est parce que le Bigdecimal n'a pas perdu, et si vous divisez 1/3 par exemple, le résultat sera un nombre décimal répété à l'infini. 0.33333333 ... théoriquement, si vous multipliez, vous obtenez le résultat exact. Mais, un nombre infini générera un débordement de pile et dans ce cas l'exception sera lancée.
Ma solution:
try {
result = n1.divide(n2);
} catch (ArithmeticException e){
Log.d("Error bigdecimal", e.toString());
result = (n1.doubleValue() / n2.doubleValue());
};
dans ce cas, votre résultat ne sera pas réduit par l'arrondi
Votre programme ne sait pas quelle précision utiliser pour les nombres décimaux, il jette:
Java.lang.ArithmeticException: Non-terminating decimal expansion
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