Repository navigation
IntMath.sum(int[]), and likewise #309
Description
Activity
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:
AcceptedOriginal 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.
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.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.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.Original comment posted by fry@google.com on 2011-01-26 at 10:16 PM
(No comment entered for this change.)
Labels:
Type-EnhancementOriginal 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.
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."
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; }Original comment posted by kevinb@google.com on 2011-07-13 at 06:18 PM
(No comment entered for this change.)
Status:
TriagedOriginal comment posted by cpovirk@google.com on 2011-07-13 at 08:40 PM
(No comment entered for this change.)
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.
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...)
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.
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.
19 remaining items
Any progress on this issue?
Many people use guava as a backfill of Java 8 functionality for Java 7-and-earlier projects (like Android).
Reacted by jkozlov, youngrafi and Maaartinus@lowasser shall we bring this to API review?
Reacted by jkozlovEven 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::sumsounds 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.
Reacted by jkozlov@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);
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));
@jbduncan Agreed. I guess, your
sum(int[])is as fast as it can get (note that you need nocheckedAdd), but yoursum(long[])is probably much slower than slicing thelonginto twoints, accumulating each into alongand usingBigIntegerfor the final result only.Agreed. I guess, your
sum(int[])is as fast as it can get (note that you need nocheckedAdd)...Am I right to think that it's because a
singlelong is large enough to hold the sum of anint[Integer.MAX_VALUE]where all elements are equal to eitherInteger.MAX_VALUEorInteger.MIN_VALUE?Regardless, I think that
LongMath::checkedAddwould almost certainly be needed when dealing with Streams with more thanInteger.MAX_VALUEelements (which aren't common at all, I imagine). But then again, in such a situation, I imagine mapping and reducing to aBigIntegerwould be more sensible than reducing to alonganyway....but your
sum(long[])is probably much slower than slicing thelonginto twoints, accumulating each into alongand usingBigIntegerfor the final result only.I'm a bit lost but very curious by what you mean here. Can you give me a code example?
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.
Reacted by Jonathan Bluett-DuncanIs this covered by
Stats.of(1, 2, 3, ...).sum(), etc.?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.
Statsis indeed very slow. I've written a simple benchmark which compares direct array summation andStats.sum.Statsis 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
Original issue created by hein.meling on 2010-01-05 at 11:15 PM
Suggest to provide:
sum()
average()
for Ints, Longs, Floats etc.