1

I have a method with a Number parameter and have to determine if it is smaller than an int. What I came up with is this :

Integer.valueOf(myInt) > (Integer) myNumber

Which looks rather clumsy for such a simple task. Moreover, I am not sure if it would play nicely with BigDecimal et.al., and what cases would I have to test?

How could it be improved?

Thank you

kostja
  • 60,521
  • 48
  • 179
  • 224
  • Are you sure that the passed Number will always be an Integer ? There may be a cast exception in the example. – StKiller Dec 02 '11 at 12:20
  • I am not, that's why I am asking about BigInteger, because it is also possible – kostja Dec 02 '11 at 12:27
  • 1
    Take a look at this: http://stackoverflow.com/questions/480632/why-doesnt-java-lang-number-implement-comparable – CKuck Dec 02 '11 at 12:32

4 Answers4

4

Your code will result in a ClassCastException if the myNumber is anything but an Integer.

I'd say this has the best chance of dealing correctly with all Number types:

myInt > myNumber.doubleValue()

because double has the widest range of all the types you can convert a Number to, and it will not truncate fractions.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • btw. Why use doubleValue() for comparing to an int? wouldnt intValue() make more sense? Or are there some quirks? – kostja Dec 02 '11 at 12:40
  • @kostja: The Number may have a fractional part, which intValue() would truncate, leading to wrong results for the comparison (perhaps not in your case but definitely for others) – Michael Borgwardt Dec 02 '11 at 13:04
4

You might have a problem here if myNumber is an instance of Long. You might end up having overflow issues (what if your Number is actually greater than Integer.MAX_VALUE?).

Also, your Number could be a double, and a conversion to int would cause a loss of precision, as your number would be truncated.

Converting your number to double could be a reasonable solution:

myInt > myNumber.doubleValue();
Vivien Barousse
  • 20,555
  • 2
  • 63
  • 64
2
myInt > myNumber.intValue()

But that would drop information.

(double)myInt > myNumber.doubleValue()
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
2

The comparison gets a little tricky because BigDecimal and BigInteger also extend Number. These classes can hold integer values of unlimited size (well, limited by the memory on your computer).

Thus, if you ask for for the double value or long value of these you may risk erroneous comparisons since BigDecimal or BigInteger will be forced to truncate their value.

The safest thing to do would be to convert the Number to a String and then give this String to the BigDecimal class to parse.

eg.

Number n = ...;
int i = ...;

BigDecimal m = new BigDecimal(n.toString());
BigDecimal j = new BigDecimal(i);

boolean result = j.compareTo(m) < 0;
// equivalent to i < n

If you're sure you will never get an instance of BigInteger or BigDecimal whose value exceeds the maximum positive or maximum negative value of a double then it should be safe to use Number.doubleValue to get a number to compare to.

There are additional problems that you may face with the possibility of having to compare BigDecimals. This is because BigDecimals represent their values in base 10, whereas other Number subclasses use base 2.

As such new BigDecimal("0.1") is not equal to 0.1d or 0.1f. This is because floats and doubles cannot represent many base 10 fractions accurately (whereas BigDecimal can). So getting a double value from a BigDecimal may end up giving you erroneous comparisons. But since you are comparing to ints this in a problem that you do not need to face.

Dunes
  • 37,291
  • 7
  • 81
  • 97
  • + 1 I am positive never to get an exceedingly big BigInteger in this case, but you are making a very good general point – kostja Dec 02 '11 at 13:30