Проверьте, является ли BigDecimal целочисленным значением
Может ли кто-нибудь рекомендовать эффективный способ определить, является ли BigDecimal
целочисленным значением в математическом смысле?
В настоящее время у меня есть следующий код:
private boolean isIntegerValue(BigDecimal bd) {
boolean ret;
try {
bd.toBigIntegerExact();
ret = true;
} catch (ArithmeticException ex) {
ret = false;
}
return ret;
}
... но если это необходимо, вы можете избежать накладных расходов на создание объектов. Раньше я использовал bd.longValueExact()
, чтобы избежать создания объекта, если BigDecimal
использовал его компактное представление внутри, но, очевидно, потерпел бы неудачу, если значение было слишком большим, чтобы вписаться в длинный.
Любая помощь была оценена.
Ответы
Ответ 1
В зависимости от источника/использования ваших значений BigDecimal
может быть быстрее проверить, действительно ли масштаб <= 0. Если это так, то это определенно целое значение в математическом смысле. Если оно > 0, то оно все равно может быть целочисленным значением и потребуется более дорогое испытание.
Ответ 2
Если вы используете решение scale()
и stripTrailingZeros()
, упомянутое в некоторых ответах, вы должны обратить внимание на ноль. Zero всегда является целым числом, независимо от того, какой масштаб он имеет, а stripTrailingZeros()
не изменяет масштаб нулевого BigDecimal.
Итак, вы можете сделать что-то вроде этого:
private boolean isIntegerValue(BigDecimal bd) {
return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0;
}
Ответ 3
Вы можете использовать это (просто подведя итоги из других ответов):
private boolean isIntegerValue(BigDecimal bd) {
return bd.stripTrailingZeros().scale() <= 0;
}
Ответ 4
Разделите число на 1 и проверьте остаток. Любое целое число всегда должно иметь остаток от 0 при делении на 1.
public boolean isWholeNumber(BigDecimal number) {
return number.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) == 0
}
Ответ 5
Одной из возможностей может быть проверка того, является ли scale() нулевым или отрицательным. В этом случае BigDecimal не должен иметь цифр после десятичной точки, и число должно быть математическим целым, если я правильно понимаю ваш вопрос.
Обновление. Если оно положительное, оно все равно может быть целым числом, но в этом случае вы не можете избавиться от дополнительных созданий объектов для дальнейших углубленных проверок.
Пример для такого случая приведен в stripTrailingZeros() метод javadoc (спасибо Joachim за подсказку в его ответе).
Ответ 6
Это самый чистый, который я придумал.
public static boolean isWhole(BigDecimal bigDecimal) {
return bigDecimal.setScale(0, RoundingMode.HALF_UP).compareTo(bigDecimal) == 0;
}
Ответ 7
Это можно сделать так же, как если бы кто-то проверял, является ли double целым числом, выполняя% 1 == 0. Вот как он будет искать значение BigDecimal.
public static boolean isIntegerValue(BigDecimal bd){
return bd.remainder(new BigDecimal("1")).compareTo(BigDecimal.ZERO) == 0;
}