web-dev-qa-db-fra.com

Vérifier si BigDecimal est une valeur entière

Quelqu'un peut-il recommander un moyen efficace de déterminer si une BigDecimal est une valeur entière au sens mathématique?

À l'heure actuelle, j'ai le code suivant:

private boolean isIntegerValue(BigDecimal bd) {
    boolean ret;

    try {
        bd.toBigIntegerExact();
        ret = true;
    } catch (ArithmeticException ex) {
        ret = false;
    }

    return ret;
}

... mais souhaiterait éviter la surcharge de création d'objet si nécessaire. Auparavant, j'utilisais bd.longValueExact(), ce qui éviterait de créer un objet si BigDecimal utilisait sa représentation compacte en interne, mais échouait évidemment si la valeur était trop grande pour tenir dans un long.

Toute aide appréciée.

41
Adamski

Selon la source/l'utilisation de vos valeurs BigDecimal, il peut être plus rapide de vérifier si l'échelle <= 0 en premier. Si c'est le cas, il s'agit certainement d'une valeur entière au sens mathématique. Si elle est> 0, alors pourrait rester une valeur entière et le test le plus coûteux sera nécessaire.

13
Joachim Sauer

EDIT: À partir de Java 8, stripTrailingZeroes () représente maintenant zéro

BigDecimal stripTrailingZeros ne fonctionne pas pour zéro

Alors

private boolean isIntegerValue(BigDecimal bd) {
  return bd.stripTrailingZeros().scale() <= 0;
}

Est parfaitement bien maintenant.


Si vous utilisez les solutions scale() et stripTrailingZeros() mentionnées dans certaines réponses, vous devez faire attention à zéro. Zéro est toujours un entier quelle que soit son échelle, et stripTrailingZeros() ne modifie pas l'échelle d'un BigDecimal zéro.

Donc, vous pourriez faire quelque chose comme ça:

private boolean isIntegerValue(BigDecimal bd) {
  return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0;
}
61
tobi

Divisez le nombre par 1 et vérifiez s'il en reste un. Tout nombre entier doit toujours avoir un reste de 0 lorsqu'il est divisé par 1.

public boolean isWholeNumber(BigDecimal number) {
    return number.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) == 0;
}
5
StPatrick

Vous pouvez utiliser ceci (en résumant simplement à partir d'autres réponses):

private boolean isIntegerValue(BigDecimal bd) {
  return bd.stripTrailingZeros().scale() <= 0;
}
4
emisch

Cela peut être fait de la même manière que quelqu'un vérifierait si un double est un entier, en effectuant% 1 == 0. Voici comment cela chercherait une valeur BigDecimal.

public static boolean isIntegerValue(BigDecimal bd){
  return bd.remainder(new BigDecimal("1")).compareTo(BigDecimal.ZERO) == 0;
}
1
Scott Armstrong

Ceci est le plus propre que je suis venu avec.

public static boolean isWhole(BigDecimal bigDecimal) {
    return bigDecimal.setScale(0, RoundingMode.HALF_UP).compareTo(bigDecimal) == 0;
}
0
Ian