0

Say we got 2 ordered collections of numbers. We want to compute the arithmetic difference element by element. I think we need to use List of Number in order to model the idea of 'ordered collection of numbers'. The problem is that the arithmetic difference (a banal '-' like in 3-2) is not defined for Number. I can cast everything to Double, but I'd rather prefer a clean solution.

public static <E extends Number> List<E> listDifferenceElementByElement(List<E> minuend, List<E> subtrahend) throws Exception {
    if (minuend.size() != subtrahend.size()) {
        throw new Exception("Collections must have the same size"); //TODO: better exception handling
    }
    List<E> difference = new ArrayList<E>();
    int i = 0;
    for (E currMinuend : minuend) {
        difference.add(currMinuend-subtrahend.get(i)); //error: The operator - is undefined for the argument type(s) E, E
        i++;
    }
    return difference;
}

Any idea?

卢声远 Shengyuan Lu
  • 31,208
  • 22
  • 85
  • 130
nimiq
  • 181
  • 2
  • 13
  • Why do you need the type to generic? What if you made `E` a `Double` instead? – Peter Lawrey Jan 11 '13 at 10:59
  • Let's say I want something which can work with any numeric type (Integer, Float, Double, ...) and possibly return the same type – nimiq Jan 11 '13 at 11:04
  • As an exercise, you can't do it in a simple manner. In reality it's very useful as there is not much to be gained if you had such a feature. If you care about performance you might use a `long[]` or `double[]` instead. This is what is usually used in maths libraries. – Peter Lawrey Jan 11 '13 at 11:07
  • possible duplicate of [Arithmetic operations with Java Generics](http://stackoverflow.com/questions/3873215/arithmetic-operations-with-java-generics) – assylias Jan 11 '13 at 11:09

3 Answers3

5

Since Number does not provide any subtract method, you can't do it simply. The alternatives I can think of are:

  1. use the provided doubleValue() method, and return a double, but you could lose precision if the lists contain BigDecimal for example.
  2. have one method per available Number subclass, but it could create a lot of duplicated code...
  3. restrict the type to whatever makes sense (say double if precision does not matter too much or BigDecimal if it does), which is a subcase of (2).

Option 2 could be implemented like by replacing difference.add(currMinuend-subtrahend.get(i)); by difference.add(subtract(currMinuend, subtrahend.get(i)));

Then it's only a matter of writing 10 subtract methods:

private static int subtract(int a, int b) { return a - b; }
private static double subtract(double a, double b) { return a - b; }
private static BigDecimal subtract(BigDecimal a, BigDecimal b) { return a.subtract(b); }

etc.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    BigDecimal is the way to go here – radai Jan 11 '13 at 11:01
  • @AndersR.Bystrup That's one way to do it indeed. – assylias Jan 11 '13 at 11:08
  • I somehow thought about the same possible strategies, but I think there is a better solution probably. Imagine I can inspect at runtime the type of the elements in minuend: if they are Integer or Double or so I can use the arithmetic operator '-' and return a Set of Integer or Double or so. Right? – nimiq Jan 11 '13 at 11:11
  • @Paolo You could do that, which would in the end boil down to the second option: one method per type. – assylias Jan 11 '13 at 11:12
  • @Anders R. Bystrup and assylias Yes, I will go for that, one method per type. Btw in Python I would have done it much easier (when I first moved from Java to Python I was always saying that I would have done it much easier in Java. Now that I moved back, I'm saying the opposite... lol!!) – nimiq Jan 11 '13 at 11:32
  • @Paolo you could simply implement it by creating one `subtract` method per type, which is going to be a one line method, and call it from your generic method. That should not take very long to implement. – assylias Jan 11 '13 at 11:34
1

This is nothing to do with generics, arrays, etc. Java doesn't allow operator overloading, so you cannot subtract 2 numbers with -, and the Number class doesn't define any methods for numeric operations. It can't because it might be operating on different subclasses (e.g. Integer.subtract(Double)) which would make defining the return type impossible.

You will need to use intrinsic types or BigDecimal (or similar) here, I think.

dty
  • 18,795
  • 6
  • 56
  • 82
0

If you want to work with many arithmetic type, you can set your list as a generic list, then add the handler when you want to find the difference between them. The handler check if the type is instance of Double, Integer, or anything you want. Based on each type, you could compute the difference.

enricob
  • 29
  • 3