Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does IntStream.average() always return correct result while LongStream.average() sometimes doesn't?

double average = LongStream
   .of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
   .average()
   .getAsDouble()

This returns 2.20723960999901594E18 but I'm expecting it to return -3.9416750812375014E18 instead.

On the other hand, this returns a correct result (-1.4628605853333333E9):

double average = IntStream
   .of(-1282256274, -1645263673, -1461061809)
   .average()
   .getAsDouble()

Why does IntStream.average() always return a correct average value and LongStream.average() sometimes doesn't?

like image 724
ZhekaKozlov Avatar asked Mar 28 '26 23:03

ZhekaKozlov


1 Answers

The sum of the inputs exceeds the range of a long so the values wrap around to positive. (This is usually referred to as negative overflow. Usually underflow applies only to floating point, but it's started to come into usage to mean negative integer overflow.)

To fix, convert to double before computing the average:

double average = LongStream
   .of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
   .mapToDouble(x -> x)
   .average()
   .getAsDouble();

-3.9416750812375014E18

(update)

Overflow can also occur with IntStream, but it doesn't happen with the second example:

IntStream
    .of(-1282256274, -1645263673, -1461061809)
    .average()

The reason is that the intermediate values for the average operation on IntStream are converted to long variables. Even though summing these values as int will overflow, after conversion to long they won't. See the source code for IntPipeline.

Of course, if you provide enough int values in an IntStream, they will potentially overflow the intermediate long variables and you'll have the same problem.

You always have to watch out for overflow when dealing with large magnitudes or large numbers of integral values. There's no escaping it.

like image 62
Stuart Marks Avatar answered Apr 01 '26 06:04

Stuart Marks



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!