views:

178

answers:

6

In Java, all numeric types extend from java.lang.Number. Would it be a good idea to have a method like the following:

public boolean areEqual(Number first, Number second) {
    if (first != null && second != null) {
        return first.equals(second);
    }
}

I'm concerned about cases where a double 2.00000 does not equal an int 2. Are these handled by the built-in equals? If not, is there any way to write a simple number compare function in java? (external libraries such as apache commons are ok)

+15  A: 
polygenelubricants
+3  A: 

The specific method you suggest would fail, because it's using equals() inherited from Object. That is, it would check to see if the Number objects were the same, not whether their values were the same.

If that was just an illustrative example, I will update my answer.

polygene's answer actually pretty much covers the ground I was heading for. You may also be interested in this question: Why doesn't java.lang.Number implement Comparable?.

Lord Torgamus
Who downvoted this? Care to explain?
polygenelubricants
A: 

you cannot call

number.equals(number2);

because, if number is a Double and number2 is an Integer, they will not be of the same class and you will get an exception telling you of that fact.

You could write a comparison class yourself that accepts Number objects, but you will have to take into account the different subclasses of Number

Richard
`System.out.println(new Double(0).equals(new Long(0)));` prints `false`; it doesn't throw any `Exception`.
polygenelubricants
Seems I was wrong. Apologies for the wrong info
Richard
+1  A: 

If you want to know whether the object references are the same, then the existing methods fit the bill. A Double representing 2.0 and an Integer representing 2 are definitely different objects, and certainly not interchangeable in a general sense.

If you just want to know whether the numeric values are the same, you can use the Number.doubleValue() method to convert both numbers to doubles, then compare those numbers together (probably allowing for a small tolerance, as most numbers are represented inexactly, such as 1.99999999996583 for what should be 2, depending on the intermediate calculation steps). Something like the following:

private static final double EPSILON = 0.000000000000001d;    

public static boolean areEquivalentNumbers(Number a, Number b)
{
   if (a == null)
   {
      return b == null;
   }
   else if (b == null)
   {
      return false;
   }
   else
   {
      return Math.abs(a.doubleValue() - b.doubleValue()) < EPSILON;
   }
}
Andrzej Doyle
A: 

Comparing numbers between integer and floating point is almost never going to yield what you are after. If however this is a simple exercise, you could implement the comparison by comparing the string representations of the values, as in:

public boolean areEqual(Number first, Number second) {
    if (first == null) {
        return second == null;
    }
    if (second == null) {
        return false;
    }

    return first.toString().equals(second.toString());
}
rsp
Interesting approach! Probably not great for large numbers of comparisons though, due to `String` operation inefficiency.
Lord Torgamus
A: 

On a tangent to a couple of the responses, may I suggest that instead of writing something like:

boolean compare(Object o1, Object o2)
{
  if (o1==null)
    return o2==null;
  if (o2==null)
    return false;
  return o1.equals(o2);
}

It's much more concise, and I believe slightly more efficient, to write:

boolean compare(Object o1, Object o2)
{
  return o1==o2 || o1!=null && o2!=null && o1.equals(o2);
}

If both are null, o1==o2 will return true. If they're not but they're the same object, that's fine too.

Technically the o2!=null is not necessary for most implementations of equals, but if you were really being so generic as to do this on Objects as in the above example, you of course wouldn't know how every override was written.

Jay