web-dev-qa-db-fra.com

Quelles sont les causes de l'exception "Expansion décimale sans terminaison" de BigDecimal.divide?

J'ai déjà utilisé BigDecimals mais pas très souvent et je travaillais sur quelque chose ce matin et j'ai continué à recevoir l'exception suivante:

Exception in thread "main" Java.lang.ArithmeticException: Non-terminating decimal expansion;
no exact representable decimal result.
    at Java.math.BigDecimal.divide(BigDecimal.Java:1594)

J'essayais de définir l'échelle et d'utiliser l'arrondi pour éliminer le problème comme suit:

    BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
    BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
    BigDecimal bd3 = bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP);
    System.out.println("result: " + bd3);

Cependant, je reçois toujours la même exception. Quelqu'un peut-il me montrer où j'ai fait une erreur?

22
ChadNC

Lorsque vous utilisez divide, vous devez utiliser un MathContext au cas où le résultat exact aurait un nombre infini de décimales (ce qui est votre cas):

MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, mc);

ou bien:

BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP);
53
assylias

Voici le problème

bd1.divide(bd2)

Vous devez utiliser l'une des méthodes divide() surchargées qui prend un mode d'arrondi (sous diverses formes) - vous ne pouvez pas effectuer l'arrondi après la division car avec une fraction non terminante, le résultat intermédiaire devrait déjà être arrondi ou nécessitent un espace de stockage infini.

4

Par défaut, BigDecimal tente de renvoyer la valeur exacte de l'expression de division donnée. Pour cette raison, si la valeur exacte ne peut pas être déterminée en raison d'une expansion décimale infinie, une ArithmeticException est levée. Un exemple de base de ceci est la division de 1 par 3, résultant en un tiers, une valeur qui ne peut pas être représentée exactement en notation décimale.

2
FThompson

Le problème est dû à une opération (division) qui entraînerait une décimale récurrente.

La solution consiste à spécifier une échelle lors de l'exécution d'une division, par exemple:

BigDecimal one = new BigDecimal("1");
BigDecimal three = new BigDecimal("3");
BigDecimal oneDivThree = one.divide(three, 200, RoundingMode.HALF_UP);
1
Neil Coffey

Vous obtenez cette erreur en raison de la division:

  1. Par défaut, BigDecimal essaie toujours de renvoyer le résultat exact d'une opération.
  2. Pour cette raison, certaines opérations de division comme 1 divisé par 3, le quotient exact aura une expansion décimale infiniment longue. Cela entraînera l'échec de l'opération de division et générera l'erreur comme décrit ci-dessus.

Fournissez une échelle et un mode d'arrondi (comme vous l'avez fait lors de la création des BigDecimals) dans la méthode de division pour éviter cela.

Tiré de ici . Un exemple de code pour la division de travail est également fourni.

Voir aussi: documentation Java sur BigDecimal .

1
keyser

Pour résoudre ce problème, vous devez modifier le troisième élément comme suit:

BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println("result: " + bd3);
0
The Tran