Java est Bigdecimal.diviser et arrondi
au travail, nous avons trouvé un problème en essayant de diviser un grand nombre par 1000. Ce nombre est venu à partir de la base de données.
Dire que j'ai de cette méthode:
private static BigDecimal divideBy1000(BigDecimal dividendo) {
if (dividendo == null) return null;
return dividendo.divide(BigDecimal.valueOf(1000), RoundingMode.HALF_UP);
}
Quand je fais l'appel suivant
divideBy1000(new BigDecimal("176100000"))
je reçois la valeur attendue de 176100. Mais si j'essaie de la ligne ci-dessous
divideBy1000(new BigDecimal("1761e+5"))
je reçois la valeur 200000. Pourquoi cela se produit? Les deux nombres sont les mêmes avec une représentation différente et la dernière est ce que je reçois de la base de données. Je comprendre que, d'une certaine manière, la JVM divise le nombre 1761 par 1000, arrondir et remplir avec 0 à la fin.
Quelle est la meilleure façon d'éviter ce genre de comportement? Gardez à l'esprit que le nombre initial n'est pas contrôlée par moi.
5 réponses
comme spécifié dans javadoc, a BigDecimal est défini par une valeur entière et un échelle.
la valeur du nombre représenté par le BigDecimal est donc (valeur non évaluée × 10^(- échelle)).
BigDecimal("1761e+5") a l'échelle de -5 et BigDecimal(176100000) a l'échelle 0.
La division des deux BigDecimal est fait en utilisant les échelles -5 et 0 respectivement parce que les échelles ne sont pas spécifiées lors de la division. divide documentation explique pourquoi les résultats sont différents.
dividepublic BigDecimal divide(BigDecimal divisor)renvoie un
BigDecimaldont la valeur est(this / divisor), et dont l'échelle préféré est(this.scale() - divisor.scale()); si le quotient exact ne peut pas être représenté (parce qu'il a une expansion décimale sans fin) unArithmeticExceptionest levée.Paramètres:
divisor- valeur par laquelle ce Granddécimal est pour être divisé.Renvoie:
this / divisorlancers:
ArithmeticException- si le quotient exact n'a pas d'expansion décimale finaleCar:
1,5
si vous spécifiez une échelle lors de la division, par exemple dividendo.divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP) vous aurez le même résultat.
les expressions new BigDecimal("176100000") et new BigDecimal("1761e+5")différent. BigDecimal garde une trace de la valeur et de la précision.
BigDecimal("176100000") a 9 chiffres de précision et est représenté à l'intérieur comme le BigInteger("176100000"), multiplié par 1. BigDecimal("1761e+5") a 4 chiffres de précision et est représenté à l'intérieur comme le