Skip to content

IntMath.sum(int[]), and likewise #309

Description

@gissuebot

Original issue created by hein.meling on 2010-01-05 at 11:15 PM


Suggest to provide:

sum()
average()

for Ints, Longs, Floats etc.

Activity

  1. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by kevinb@google.com on 2010-01-06 at 01:00 AM


    Agreed.

    Varargs?

    The best way to implement Longs.average() is a somewhat interesting puzzle.


    Status: Accepted

  2. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by gpampara on 2010-01-06 at 05:21 AM


    Could you please elaborate at what the complexities are?

    I think I'm missing something.

  3. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by hein.meling on 2010-01-06 at 08:12 AM


    About varargs; currently I have this:

    int sum(Collection<Integer> c)

    in my project. Not sure if such a collection can be transformed into an array without copying; if so varargs are
    fine, otherwise I would like to have both.

    Another issue that come to mind when I started to think about test cases for this was: what to return if the sum
    exceeds the limit of its primitive type. (maybe this was what you were referring to as a puzzle with
    Longs.average()?)

    We have to avoid any silent overflows for this. Maybe the return type should be Number to allow
    BigInteger/Decimal to be returned for those cases.

  4. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by ogregoire on 2010-01-06 at 03:03 PM


    for the Longs.average() wouldn't it be interesting to use BigInteger as internal
    mechanics?

    Or use an integer to keep track of the number of times the overflow (or underflow) is
    reached.

  5. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by kevinb@google.com on 2010-01-06 at 04:54 PM


    Yup, BigInteger is the simple solution, but I'm quite curious to benchmark simpler
    alternatives.

    As for what to do in the case of overflow, I think ArithmeticException seems
    appropriate.

  6. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by fry@google.com on 2011-01-26 at 10:16 PM


    (No comment entered for this change.)


    Labels: Type-Enhancement

  7. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by j...@nwsnet.de on 2011-01-27 at 09:07 AM


    I'd like to have each method to accept iterable, too.

    While looking at my custom math utilities: What about rate and percentage calculation? Like this:

      public static double calculateRate(double count, double total) {
        // Compare against 0.0 to prevent infinity as result.
        return total == 0.0 ? 0.0 : count / total;
      }

    This might be useful to implement for multiple primitives as one might be dealing with doubles or floats etc. depending on the application.

  8. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by wasserman.louis on 2011-03-15 at 05:24 PM


    I'm up for writing this, including some attempts I've thought of for "simpler alternatives."

  9. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by raymondofrish on 2011-03-16 at 02:01 AM


    How about something like the following? Not thorough benchmarked or optimized, but surely better than BigInteger, no? I hear there's a nice microbenchmarking tool available for Java...

    public static long average(Iterable<Long> longs) {
        long count = Iterables.size(longs);
    
        long integerSum = 0;
        long remainderSum = 0;
    
        for (long num : longs) {
            integerSum += num / count;
            remainderSum += num % count;
        }
    
        return integerSum + remainderSum / count;
    }
    
  10. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by kevinb@google.com on 2011-07-13 at 06:18 PM


    (No comment entered for this change.)


    Status: Triaged

  11. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by cpovirk@google.com on 2011-07-13 at 08:40 PM


    (No comment entered for this change.)

  12. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by blank101 on 2011-07-19 at 07:06 PM


    Recollecting back to my numerical methods class, there are also some interesting issues for the floating point primitives when calculating sum/average values beyond (over|under)flow.

  13. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by wasserman.louis on 2011-10-18 at 11:26 PM


    Revisiting...

    I'm thinking we might just provide sum(), which has a less ambiguous return type.

    In particular:

    long IntMath.sum(int... ints)
    BigInteger LongMath.sum(long... longs)

    since we can safely assume that the sum of an array of ints will fit into a long. (The result will fit in 96 bits, so we can do intermediate accumulation with smaller types, too...)

  14. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by j...@nwsnet.de on 2011-10-19 at 07:53 AM


    So iterables are not supported as arguments? I've got a lot of them floating around when creating reports.

  15. gissuebot commented on Oct 31, 2014

    @gissuebot
    Author

    Original comment posted by dancerjohn on 2011-10-19 at 10:35 AM


    You can use Longs.toArray(Lists.newArrayList(myIterable)) to convert to an array and pass to a varargs.

  16. 19 remaining items

  17. orionll commented on Jul 21, 2015

    @orionll

    Any progress on this issue?

  18. jcogilvie commented on Nov 2, 2015

    @jcogilvie

    Many people use guava as a backfill of Java 8 functionality for Java 7-and-earlier projects (like Android).

  19. ronshapiro commented on Oct 4, 2017

    @ronshapiro
    Contributor

    @lowasser shall we bring this to API review?

  20. Maaartinus commented on Oct 4, 2017

    @Maaartinus

    Even with Java 8, there seem to be some methods missing:
    ...
    long LongMath.sum(int[])
    BigInteger BigIntegerMath.sum(long[])
    ...
    I'm not sure about choosing the classes according to the result type, but there are already precedents in Guava (e.g., factorial(int)). Both methods are rather simple, but getting them wrong isn't too hard either.

    Using IntStream::sum sounds like a bad idea in case it might overflow one day and you might spend the next one chasing the bug.

    Varargs or int/long streams arguments may be better.

  21. jbduncan commented on Oct 4, 2017

    @jbduncan
    Contributor

    @Maaartinus With regards to LongMath.sum(int[]), I believe one can emulate it for now with both streams and Guava's help, like so. (I've not run this code example through a compiler, so it may need some tweaking, but I hope the idea comes across well.)

    int[] ints = ...;
    long sum = Arrays.stream(ints).mapToLong(i -> i).reduce(0, LongMath::checkedAdd);
  22. jbduncan commented on Oct 4, 2017

    @jbduncan
    Contributor

    Likewise, for BigIntegerMath.sum(long[]), something like this should work:

    long[] longs = ...;
    BigInteger sum = Arrays.stream(longs).mapToObj(BigInteger::valueOf).reduce(BigInteger.ZERO, (a, b) -> a.add(b));
  23. Maaartinus commented on Oct 6, 2017

    @Maaartinus

    @jbduncan Agreed. I guess, your sum(int[]) is as fast as it can get (note that you need no checkedAdd), but your sum(long[]) is probably much slower than slicing the long into two ints, accumulating each into a long and using BigInteger for the final result only.

  24. jbduncan commented on Oct 6, 2017

    @jbduncan
    Contributor

    @Maaartinus

    Agreed. I guess, your sum(int[]) is as fast as it can get (note that you need no checkedAdd)...

    Am I right to think that it's because a single long is large enough to hold the sum of an int[Integer.MAX_VALUE] where all elements are equal to either Integer.MAX_VALUE or Integer.MIN_VALUE?

    Regardless, I think that LongMath::checkedAdd would almost certainly be needed when dealing with Streams with more than Integer.MAX_VALUE elements (which aren't common at all, I imagine). But then again, in such a situation, I imagine mapping and reducing to a BigInteger would be more sensible than reducing to a long anyway.

    ...but your sum(long[]) is probably much slower than slicing the long into two ints, accumulating each into a long and using BigInteger for the final result only.

    I'm a bit lost but very curious by what you mean here. Can you give me a code example?

  25. Maaartinus commented on Oct 6, 2017

    @Maaartinus

    Am I right to think

    Yes, the minimum value is > Integer.MAX_VALUE * Integer.MIN_VALUE > -2**62, which fits, the maximum value is slightly smaller in magnitude.


    a code example

    long MASK = 0xFFFFFFFFL;
    long high = 0, low = 0;
    for (long x : longs) {
         low += x & MASK;
         high += x >> 32;
    }
    return BigInteger.valueOf(high).shiftLeft(32).add(BigInteger.valueOf(low));
    

    There may be tons of errors.

  26. netdpb commented on Aug 5, 2019

    @netdpb
    Member

    Is this covered by Stats.of(1, 2, 3, ...).sum(), etc.?

  27. kevinb9n commented on Aug 5, 2019

    @kevinb9n
    Contributor

    Only technically, but I would not expect Stats to be a good choice in cases where the Stats instance is immediately thrown away. It does too much extra work.

  28. orionll commented on Aug 6, 2019

    @orionll

    Stats is indeed very slow. I've written a simple benchmark which compares direct array summation and Stats.sum. Stats is 7-10x time slower:

    Benchmark             (size)  Mode  Cnt    Score     Error  Units
    Statistics.sum            10  avgt    4    0,010 ?   0,001  us/op
    Statistics.sum          1000  avgt    4    0,861 ?   0,011  us/op
    Statistics.sum        100000  avgt    4   86,060 ?   1,232  us/op
    Statistics.sumStats       10  avgt    4    0,077 ?   0,017  us/op
    Statistics.sumStats     1000  avgt    4    8,608 ?   0,133  us/op
    Statistics.sumStats   100000  avgt    4  863,270 ?  31,961  us/op
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions