double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.average()
.getAsDouble()
这会返回 2.20723960999901594E18
但我希望它会返回 -3.9416750812375014E18
。
另一方面,这会返回正确的结果(-1.4628605853333333E9
):
double average = IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
.getAsDouble()
为什么 IntStream.average()
总能返回正确的平均值而 LongStream.average()
有时却不能?
最佳答案
输入的总和超出了 long
的范围,因此值环绕为正数。 (这通常称为负溢出。通常下溢仅适用于 float ,但它开始用于表示负整数溢出。)
要修复,在计算平均值之前转换为 double:
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.mapToDouble(x -> x)
.average()
.getAsDouble();
-3.9416750812375014E18
(更新)
IntStream
也可能发生溢出,但第二个示例不会发生:
IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
原因是 IntStream
上的 average
操作的中间值被转换为 long
变量。尽管将这些值相加为 int
会溢出,但在转换为 long
后它们不会溢出。查看source code for IntPipeline .
当然,如果您在 IntStream
中提供足够的 int
值,它们可能会溢出中间的 long
变量,您将拥有同样的问题。
在处理大数量级或大量整数值时,您始终必须注意溢出。无法逃避。
关于java - 为什么 IntStream.average() 总是返回正确的结果而 LongStream.average() 有时却不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47107300/