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.
divide
public BigDecimal divide(BigDecimal divisor)
renvoie un
BigDecimal
dont 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) unArithmeticException
est levée.Paramètres:
divisor
- valeur par laquelle ce Granddécimal est pour être divisé.Renvoie:
this / divisor
lancers:
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