Как сравнить два числа на Java?

Возможный дубликат:
Сравнение значений двух общих чисел

Я хотел бы сравнить два произвольных экземпляра Number, чтобы узнать, что больше. Как вы знаете, это могут быть целые числа, длинные или парные, а также BigIntegers или BigDecimals. Итак, что делать?

  • Число не реализует Comparable.
  • Нельзя использовать doubleValue(), поскольку может быть потеря точности из BigDecimals или BigIntegers.

Нужно ли мне проходить экзамен по экземплярам и кастинг? Должна быть какая-то библиотека, которая это делает. Но я уже проверял Apache Commons и Guava без везения.

Изменить 1: Комментарии указали на это: Сравнение значений двух общих чисел. Он имеет решение, которое преобразует все в BigDecimal с помощью toString(). Нет ли лучшего способа сделать это?

Изменить 2: Я только что разместил свою собственную версию в качестве ответа на другой вопрос. Он должен быть более эффективным и надежным, чем принятый ответ.

Ответ 1

Вы не можете сравнить два произвольных экземпляра типа Number, потому что это возможно бесконечная операция. Представьте себе два иррациональных числа, где единственное различие находится в миллиардном десятичном значении. Для этого вам придется сравнить несколько миллиардов десятичных знаков.

Вам нужно преобразовать экземпляры Number в BigDecimal, применив округление по мере необходимости, а затем сравните их оба.

Ответ 2

Строго говоря, число нельзя сравнивать. Сначала вам нужно определить семантику сравнения. Поскольку вы упоминали его для использования в библиотеке, вы, вероятно, хотите только полагаться на то, что предлагает Number API.

Так сводится к сравнению значений longValue() или doubleValue(). Я предлагаю подход, который сначала сравнивает использование longValue(), и если они окажутся равными, сравните doubleValue() (таким образом, вы поймаете длинные переполнения, но при этом сохраняете точность в 64 бит, когда значения не являются float)

public static int compare(Number n1, Number n2) {
    long l1 = n1.longValue();
    long l2 = n2.longValue();
    if (l1 != l2)
        return (l1 < l2 ? -1 : 1);
    return Double.compare(n1.doubleValue(), n2.doubleValue());
}

Все остальное - игра с угадыванием, превышающая то, что предлагает Number API. Для стандартного использования код выше должен работать достаточно хорошо. И да, если вы передадите его (например) BigIntegers или BigDecimals, которые находятся за пределами диапазона значений Doubles или имеют отличия только за пределами 53 бит точности мантиссы, они ошибочно распознаются как равные, но в отношении API-интерфейса Number этот неправильный результат можно рассматривать как "правильный".