Zhe*_*lov 2 java java-8 java-stream
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.average()
.getAsDouble()
Run Code Online (Sandbox Code Playgroud)
这会返回,2.20723960999901594E18但我希望它会返回-3.9416750812375014E18.
另一方面,这会返回正确的结果(-1.4628605853333333E9):
double average = IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
.getAsDouble()
Run Code Online (Sandbox Code Playgroud)
为什么IntStream.average()总是返回正确的平均值,LongStream.average()有时却没有?
输入的总和超出a的范围,long因此值环绕为正.(这通常被称为负溢出.通常下溢仅适用于浮点,但它开始用于表示负整数溢出.)
要修复,在计算平均值之前转换为double:
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.mapToDouble(x -> x)
.average()
.getAsDouble();
-3.9416750812375014E18
Run Code Online (Sandbox Code Playgroud)
(更新)
溢出也可能发生IntStream,但第二个例子不会发生:
IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
Run Code Online (Sandbox Code Playgroud)
原因是average操作的中间值IntStream被转换为long变量.即使将这些值相加int也会溢出,转换后long它们也不会.请参阅IntPipeline的源代码.
当然,如果你int在a中提供了足够的值IntStream,它们可能会溢出中间long变量,你会遇到同样的问题.
在处理大量或大量积分值时,您总是需要注意溢出.没有逃脱它.