Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle if sum of integer array exceeds int max value(2147483647) using Arrays Stream?

I have an integer array and want to sum all it's elements. It's working fine as far as sum is less than or equal to int max value(2147483647) but it's failing as soon as sum exceeds int max value. Below is the example-:

int [] iArr = new int[]{2147483646 , 1 , 1};
    System.out.println(Arrays.stream(iArr).sum());

Result-: -2147483648

As we can see above result is incorrect. I know that it can be resolved by using long array instead if int array as below.

long [] iArr = new long[]{2147483646 , 1 , 1};
    System.out.println(Arrays.stream(iArr).sum());

Result-: 2147483648

But I don't want to use long array because I know that maximum size limit of elements of array is with in int max value(2147483647). Hence I don't want to waste memory. Is there any other way to sum of integer array which(sum of elements of array) exceeds int max value(2147483647) using Array Stream?

like image 348
Ashish Kumar Avatar asked Dec 18 '22 11:12

Ashish Kumar


2 Answers

You don’t need a long[] array, just to process the values as longs. The solution is as easy as one can imagine:

int[] iArr = new int[]{2147483646 , 1 , 1};
System.out.println(Arrays.stream(iArr).asLongStream().sum());

It’s unlikely to ever exceed the long range, as even if all elements are as big as Integer.MAX_VALUE, you would need 4294967298 stream elements to reach Long.MAX_VALUE. But if you have such a large stream and lots of time, or when a LongStream is your starting point, you can resort to BigInteger as follows:

long[] lArr={ Long.MAX_VALUE, Long.MAX_VALUE, 42 };
System.out.println(Arrays.stream(lArr).mapToObj(BigInteger::valueOf)
                         .reduce(BigInteger.ZERO, BigInteger::add));

note that this also works for IntStreams, as the promotion from int to long happens automatically when calling BigInteger.valueOf(long), but as said above, this is rarely needed.

like image 136
Holger Avatar answered Dec 21 '22 01:12

Holger


This questions has already been answered but I found one more way to accomplish above task optimally. That's why I thought to share that with execution time statistics. asLongStream method of stream works optimally to convert integer stream to long.

int[] iArr = new int[10000000];
Arrays.fill(iArr , 3132);   

long iStart = System.nanoTime();
long  lSum1 = Arrays.stream(iArr).mapToLong(Long::valueOf).sum();
long iEnd = System.nanoTime();

System.out.println("Sum-: " + lSum1);
System.out.println("Time in nanoseconds-: " + (iEnd - iStart) + "ns using \"mapToLong\"\n");

long iStart1 = System.nanoTime();
long lSum2 = Arrays.stream(iArr).asLongStream().sum();
long iEnd1 = System.nanoTime();

System.out.println("Sum-: " + lSum2);
System.out.println("Time in nanoseconds-: " + (iEnd1 - iStart1) + "ns using \"asLongStream\"\n");

long iStart2 = System.nanoTime();
long lSum3 = Arrays.stream(iArr).boxed().collect(Collectors.summingLong(Integer::longValue));
long iEnd2 = System.nanoTime();

System.out.println("Sum-: " + lSum3);
System.out.println("Time in nanoseconds-: " + (iEnd2 - iStart2) + "ns using \"Collectors\"\n");

Output-:

Sum-: 31320000000
Time in nanoseconds-: 230369419ns using "mapToLong"

Sum-: 31320000000
Time in nanoseconds-: 109999469ns using "asLongStream"

Sum-: 31320000000
Time in nanoseconds-: 188769476ns using "Collectors"

like image 29
Ashish Kumar Avatar answered Dec 20 '22 23:12

Ashish Kumar