Exception arithmétique: "expansion décimale sans fin; Pas de résultat décimal représentatif exact"
Pourquoi le code suivant lever 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.
9 réponses
From the Java 8 docs:
Lorsqu'un objet MathContext est fourni avec un paramètre de précision de 0 (pour exemple, MathContext.Illimité), les opérations arithmétiques sont exactes, comme sont les méthodes arithmétiques qui ne prennent aucun objet MathContext. (C'est le seul comportement qui a été pris en charge dans les versions antérieures à 5.)
comme corollaire du calcul du résultat exact, le réglage du mode d'arrondi d'un MathContext objet avec un paramètre de précision de 0 n'est pas utilisé et donc non pertinent. Dans le cas de diviser, le quotient exact pourrait avoir un décimal infiniment long expansion; par exemple, 1 divisé par 3.
si le quotient a une expansion décimale Non interminable et l'opération est spécifiée pour retourner un résultat exact, une exception arithmétique est lancée. Sinon, le résultat exact de la division est retourné, comme fait pour d'autres opérations.
pour fixer, 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 arrondi. BigDecimal se plaint qu'il pourrait utiliser 10, 20, 5000, ou l'infini décimale des places, et il ne serait toujours pas en mesure de vous donner une représentation exacte du nombre. Donc au lieu de vous donner un faux BigDecimal, il se moque de vous.
cependant, si vous fournissez un mode rond et une précision, alors il sera en mesure de convertir (par exemple. 1.333333333-de-l'infini à quelque chose comme 1.3333 ... mais en tant que programmeur, vous devez lui dire avec quelle précision vous êtes "heureux".
Vous pouvez le faire
a.divide(b, MathContext.DECIMAL128)
vous pouvez choisir le nombre de bits que vous voulez soit 32,64,128.
voir ce lien:
pour la fixation d'une telle question j'ai utilisé ci-dessous le code
a.divide(b, 2, RoundingMode.HALF_EVEN)
2 est la précision. Maintenant le problème a été résolu.
j'ai eu ce même problème, parce que ma ligne de code était:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
je change à ceci, la lecture de la réponse précédente, parce que je n'écrivais pas de précision décimale:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4 Est décimal Precion
et RoundingMode sont des constantes Enum, vous pouvez choisir n'importe lequel de ces
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 le RoundingMode
information ici: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration /
Answer for BigDecimal Lakes 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")));
}
Ajouter objet MathContext dans votre appel de méthode divide et ajuster la précision et le mode 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, il en résultera une répétition décimale à l'infini. 0,33333333... théoriquement, si vous multipliez retour, vous recevez le résultat exact. Mais, un nombre infini générera pile sur flux et dans ce cas l'exception est 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 coupé en arrondissant
votre programme ne sait pas quelle précision pour les nombres décimaux à utiliser de sorte qu'il jette:
java.lang.ArithmeticException: Non-terminating decimal expansion
Solution de contournement exception:
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
de Ses une question d'arrondir le résultat, la solution pour moi est la suivante.
divider.divide(dividend,RoundingMode.HALF_UP);