Подтвердить что ты не робот

Проверьте, является ли BigDecimal целочисленным значением

Может ли кто-нибудь рекомендовать эффективный способ определить, является ли BigDecimal целочисленным значением в математическом смысле?

В настоящее время у меня есть следующий код:

private boolean isIntegerValue(BigDecimal bd) {
    boolean ret;

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

    return ret;
}

... но если это необходимо, вы можете избежать накладных расходов на создание объектов. Раньше я использовал bd.longValueExact(), чтобы избежать создания объекта, если BigDecimal использовал его компактное представление внутри, но, очевидно, потерпел бы неудачу, если значение было слишком большим, чтобы вписаться в длинный.

Любая помощь была оценена.

4b9b3361

Ответ 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;
}