TL; DR
Utilisez l'un de ceux-ci pour les besoins de conversion universels
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
Raisonnement
La réponse dépend des exigences et de la manière dont vous répondez à ces questions.
- Y aura-t-il
BigDecimal
potentiellement une partie fractionnaire non nulle?
- Le
BigDecimal
potentiel ne rentrera- t-il pas dans la Integer
gamme?
- Souhaitez-vous des parties fractionnaires non nulles arrondies ou tronquées?
- Comment souhaitez-vous arrondir les parties fractionnaires non nulles?
Si vous avez répondu non aux 2 premières questions, vous pouvez simplement utiliser BigDecimal.intValueExact()
comme d'autres l'ont suggéré et laisser exploser quand quelque chose d'inattendu se produit.
Si vous n'êtes pas absolument sûr à 100% de la question numéro 2, intValue()
c'est toujours la mauvaise réponse.
Faire mieux
Utilisons les hypothèses suivantes basées sur les autres réponses.
- Nous sommes d'accord pour perdre de la précision et tronquer la valeur parce que c'est ce que font
intValueExact()
et l'auto-boxing
- Nous voulons qu'une exception soit levée lorsque le
BigDecimal
est plus grand que la Integer
plage car tout le reste serait fou à moins que vous n'ayez un besoin très spécifique pour le bouclage qui se produit lorsque vous supprimez les bits de poids fort.
Étant donné ces paramètres, intValueExact()
lève une exception lorsque nous ne le voulons pas si notre partie fractionnaire est non nulle. D'autre part, intValue()
ne lève pas d'exception quand il le devrait si notre BigDecimal
est trop grand.
Pour tirer le meilleur parti des deux mondes, arrondissez le BigDecimal
premier, puis convertissez-vous. Cela a également l'avantage de vous donner plus de contrôle sur le processus d'arrondi.
Test de Spock Groovy
void 'test BigDecimal rounding'() {
given:
BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99)
BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99)
BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000")
String decimalAsBigIntString = decimal.toBigInteger().toString()
String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString()
String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString()
expect: 'decimals that can be truncated within Integer range to do so without exception'
//GOOD: Truncates without exception
'' + decimal.intValue() == decimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
// decimal.intValueExact() == decimalAsBigIntString
//GOOD: Truncates without exception
'' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648
//'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
//'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is 0
//'' + reallyHuge.intValue() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString
and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal'
//decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact()
}