Conversion de BigDecimal en entier

J’ai la méthode Hibernate qui me renvoie un BigDecimal. J’ai une autre méthode API à laquelle je dois passer ce nombre, mais il accepte Integer comme paramètre. Je ne peux pas modifier les types de retour ou les types de variable des deux méthodes.

Maintenant, comment convertir le BigDecimal en entier et le passer à la seconde méthode?

Y a-t-il un moyen de s’en sortir?

Vous myBigDecimal.intValueExact() (ou simplement intValue() ) et il intValue() même une exception si vous perdiez des informations. Cela retourne un int, mais l’autoboxing s’en charge.

Pouvez-vous garantir que le BigDecimal ne contiendra jamais une valeur supérieure à Integer.MAX_VALUE ?

Si oui, alors voici votre code appelant intValue :

 Integer.valueOf(bdValue.intValue()) 

TL; DR

Utilisez l’un d’eux 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.

  • Le BigDecimal aura-t-il potentiellement une partie non nulle?
  • Le BigDecimal risque-t-il de ne pas entrer dans la plage Integer ?
  • Voulez-vous des parties fractionnaires non nulles arrondies ou tronquées?
  • Comment voudriez-vous que les parties fractionnaires non nulles soient arrondies?

Si vous avez répondu non aux deux 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 2, alors intValue() est toujours la mauvaise réponse.

Le rendre meilleur

Utilisons les hypothèses suivantes basées sur les autres réponses.

  • Nous sums d’accord pour perdre de la précision et tronquer la valeur car c’est ce que font intValueExact() et la mise en boîte automatique
  • Nous voulons qu’une exception soit lancée lorsque le BigDecimal est plus grand que la plage Integer , car toute autre chose serait folle à moins que vous ayez un besoin très spécifique de bouclage qui survient lorsque vous déposez les bits de poids fort.

Compte tenu de ces parameters, intValueExact() génère une exception lorsque nous ne le souhaitons pas si notre partie fractionnaire est différente de zéro. Par contre, intValue() ne lance pas d’exception quand il le faudrait si notre BigDecimal est trop grand.

Pour obtenir le meilleur des deux mondes, arrondissez d’abord BigDecimal , puis convertissez. Cela a également l’avantage de vous donner plus de contrôle sur le processus d’arrondissement.

Test 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") Ssortingng decimalAsBigIntSsortingng = decimal.toBigInteger().toSsortingng() Ssortingng hugeDecimalAsBigIntSsortingng = hugeDecimal.toBigInteger().toSsortingng() Ssortingng reallyHugeAsBigIntSsortingng = reallyHuge.toBigInteger().toSsortingng() expect: 'decimals that can be truncated within Integer range to do so without exception' //GOOD: Truncates without exception '' + decimal.intValue() == decimalAsBigIntSsortingng //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information // decimal.intValueExact() == decimalAsBigIntSsortingng //GOOD: Truncates without exception '' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntSsortingng and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' //BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648 //'' + hugeDecimal.intValue() == hugeDecimalAsBigIntSsortingng //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information //'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntSsortingng //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntSsortingng and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' //BAD: hugeDecimal.intValue() is 0 //'' + reallyHuge.intValue() == reallyHugeAsBigIntSsortingng //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + reallyHuge.intValueExact() == reallyHugeAsBigIntSsortingng //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntSsortingng and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal' //decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact() } 

Eh bien, vous pourriez appeler BigDecimal.intValue() :

Convertit ce BigDecimal en un int. Cette conversion est analogue à une conversion primitive réduite du double au court tel que défini dans la spécification du langage Java: toute partie fractionnaire de ce BigDecimal sera ignorée et si le “BigInteger” résultant est trop grand pour tenir dans un int, seule la partie basse -ordre 32 bits sont renvoyés. Notez que cette conversion peut perdre des informations sur l’ampleur et la précision globales de cette valeur BigDecimal et renvoyer un résultat avec le signe opposé.

Vous pouvez alors appeler explicitement Integer.valueOf(int) ou laisser l’auto-boxing le faire pour vous si vous utilisez une version suffisamment récente de Java.

Ce qui suit devrait faire l’affaire:

 BigDecimal d = new BigDecimal(10); int i = d.intValue(); 

Avez-vous essayé d’appeler BigInteger # intValue () ?

Voir BigDecimal # intValue ()

J’ai trouvé que ce qui précède ne fonctionnait pas pour moi. Je tirais une valeur de cellule d’un JTable, mais je ne pouvais pas la convertir en double ou int, etc. Ma solution:

 Object obj = getTable().getValueAt(row, 0); 

où la ligne 0 serait toujours un nombre. J’espère que cela aidera quelqu’un qui défile encore!