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()
有时却没有?
答案 0 :(得分:5)
输入的总和超出了long
的范围,因此值会变为正值。 (这通常被称为负溢出。通常下溢仅适用于浮点,但它开始用于表示负整数溢出。)
要修复,请在计算平均值之前转换为double:
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.mapToDouble(x -> x)
.average()
.getAsDouble();
-3.9416750812375014E18
(更新)
IntStream
也会发生溢出,但第二个例子不会发生:
IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
原因是average
上的IntStream
操作的中间值会转换为long
个变量。即使将这些值汇总为int
也会溢出,但在转换为long
之后,它们不会。请参阅source code for IntPipeline。
当然,如果您在int
中提供了足够的IntStream
值,它们可能会溢出中间long
个变量,并且您会遇到同样的问题。
在处理大量或大量积分值时,您始终需要注意溢出。没有逃脱它。
答案 1 :(得分:-1)
数字太长了,我们正在溢出:
System.out.println(-4480186093928204294L -1340542863544260591L -6004296286240039273L);
6621718829997047458