Alex Rivera | Logout

Comparing the values of two generic Numbers

Asked 2010-04-21T13:19:54.307
75

I want to compare to variables, both of type T extends Number. Now I want to know which of the two variables is greater than the other or equal. Unfortunately I don't know the exact type yet, I only know that it will be a subtype of java.lang.Number. How can I do that?

EDIT: I tried another workaround using TreeSets, which actually worked with natural ordering (of course it works, all subclasses of Number implement Comparable except for AtomicInteger and AtomicLong). Thus I'll lose duplicate values. When using Lists, Collection.sort() will not accept my list due to bound mismatchs. Very unsatisfactory.

Edit
Report

1 Answer

18

After having asked a similar question and studying the answers here, I came up with the following. I think it is more efficient and more robust than the solution given by gustafc:

public int compare(Number x, Number y) {
    if (isSpecial(x) || isSpecial(y))
        return Double.compare(x.doubleValue(), y.doubleValue());
    else
        return toBigDecimal(x).compareTo(toBigDecimal(y));
}

private static boolean isSpecial(Number x) {
    var specialDouble = x instanceof Double d
            && (Double.isNaN(d) || Double.isInfinite(d));
    var specialFloat = x instanceof Float f
            && (Float.isNaN(f) || Float.isInfinite(f));
    return specialDouble || specialFloat;
}

private static BigDecimal toBigDecimal(Number number) {
    if (number instanceof BigDecimal d)
        return d;
    if (number instanceof BigInteger i)
        return new BigDecimal(i);
    if (number instanceof Byte || number instanceof Short
            || number instanceof Integer || number instanceof Long)
        return new BigDecimal(number.longValue());
    if (number instanceof Float || number instanceof Double)
        return new BigDecimal(number.doubleValue());
    
    try {
        return new BigDecimal(number.toString());
    } catch(NumberFormatException e) {
        throw new RuntimeException("The given number (\"" + number + "\" of class " + number.getClass().getName() + ") does not have a parsable string representation", e);
    }
}
answered 2012-10-14T16:15:43.707

Your Answer