1

I want to do math with a collection of Objects that are type Number. In this example I just want to sum them. What I could come up with currently is to just do a switch statement and then cast to a BigDecimal, as that is the largest value that I would be working with. This is working correctly right now and sums to 20.

This seems pretty involved and a large amount of work to do something pretty simple. Is there a better way to do this?

import java.math.BigDecimal;

public class NumberArray {

    public static BigDecimal sum(Number[] nums) {
        BigDecimal summation = new BigDecimal(0);

        for (Number n : nums) {
            switch (n.getClass().getName()) {
            case "java.lang.Integer":
                summation = summation.add(new BigDecimal((Integer) n));
                break;
            case "java.lang.Double":
                summation = summation.add(new BigDecimal((Double) n));
                break;
            case "java.lang.Long":
                summation = summation.add(new BigDecimal((Long) n));
                break;
            case "java.lang.Float":
                summation = summation.add(new BigDecimal((Float) n));
                break;
            case "java.math.BigDecimal":
                summation = summation.add((BigDecimal)n);
                break;
            default:
                throw new IllegalArgumentException("Unsupported num: " +n.getClass().getName());
            }
        }
        return summation;
    }

    public static void main(String[] args) {
        Number[] nums = { 1, 1, 2, 2, 1L, 1f, new BigDecimal(10), 2.0 };
        System.out.println(sum(nums));
    }
}

dftag
  • 85
  • 2
  • 8
  • 1
    [`BigDecimal#add/subtract/divide`](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/math/BigDecimal.html) might be some places to start – MadProgrammer May 30 '22 at 03:59
  • 1
    `sum = sum.add(new BigDecimal(number.doubleValue()));` where `number` is an element from the array <- put in a loop, my testing generates a result of `20` – MadProgrammer May 30 '22 at 04:12
  • Or you also do something like ... `Arrays.stream(nums).map(e -> new BigDecimal(e.doubleValue())).reduce(BigDecimal.ZERO, BigDecimal::add);` – MadProgrammer May 30 '22 at 04:13
  • 1
    @MadProgrammer e.doubleValue() would be bad in the case where e was a BigDecimal. – tgdavies May 30 '22 at 06:11
  • @tgdavies Have a better choice - was trying to avoid using `instanceof` because "it's messy" – MadProgrammer May 30 '22 at 06:12
  • 1
    Have a look at [Convert Java Number to BigDecimal : best way](https://stackoverflow.com/questions/16216248/convert-java-number-to-bigdecimal-best-way). Search for more. – Ole V.V. May 30 '22 at 06:27
  • My first change would be replacing the comparison of number type for using strings (class name) to using `Class#equals` method. Package and class names could change in future versions. – Basil Bourque May 30 '22 at 07:09
  • @OleV.V. Yep read that – MadProgrammer May 30 '22 at 08:27
  • @OleV.V. So, you're suggesting `Arrays.stream(nums).map(e -> new BigDecimal(e.toString())).reduce(BigDecimal.ZERO, BigDecimal::add)` would be a better approach? – MadProgrammer May 30 '22 at 08:33
  • 1
    @MadProgrammer I have a hard time forming an opinion on what I would prefer, and it would probably depend on circumstances. Converting via strings may also incur inaccuracies. In many situations I’d be tempted to use your first approach only with special cases for the `Number` already being a `BigDecimal` or `BigInteger` (since they may be outside the `double` range as tgdavies mentioned). – Ole V.V. May 30 '22 at 08:44
  • 1
    @OleV.V. I’d probably make the map function so it could check for an instance of BigDecimal and just return it – MadProgrammer May 30 '22 at 08:56

0 Answers0