Java 为什么IntStream.average()总是返回正确的结果,而LongStream.average()有时不返回';T
这将返回Java 为什么IntStream.average()总是返回正确的结果,而LongStream.average()有时不返回';T,java,java-8,java-stream,Java,Java 8,Java Stream,这将返回2.207239396099901594e18,但我希望它返回-3.9416750812375014E18 另一方面,这将返回正确的结果(-1.46286058533333e9): 为什么IntStream.average()总是返回正确的平均值,而LongStream.average()有时不返回正确的平均值?数字太大,太长时间,我们会溢出: double average = IntStream .of(-1282256274, -1645263673, -1461061809)
2.207239396099901594e18
,但我希望它返回-3.9416750812375014E18
另一方面,这将返回正确的结果(-1.46286058533333e9
):
为什么
IntStream.average()
总是返回正确的平均值,而LongStream.average()
有时不返回正确的平均值?数字太大,太长时间,我们会溢出:
double average = IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()
.getAsDouble()
662171882999047458输入的总和超过了
长的范围
,因此这些值都是正数。(这通常称为负溢出。通常下溢仅适用于浮点,但它开始用于表示负整数溢出。)
若要修复,请在计算平均值之前转换为double:
System.out.println(-4480186093928204294L -1340542863544260591L -6004296286240039273L);
(更新)
溢出也可能发生在IntStream
中,但在第二个示例中不会发生:
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.mapToDouble(x -> x)
.average()
.getAsDouble();
-3.9416750812375014E18
原因是IntStream
上的average
操作的中间值被转换为long
变量。即使将这些值相加为int
将溢出,但在转换为long
后,它们不会溢出。看
当然,如果在IntStream
中提供足够的int
值,它们可能会溢出中间long
变量,您也会遇到同样的问题
在处理大数量级或大量整数值时,您必须始终注意溢出。无法逃避。我知道溢出。我更好奇为什么IntStream.average()和LongStream.average()的行为不同。@ZhekaKozlov噢。你编辑了这个问题。也许这就是你被否决的原因。(我没有投反对票。)我认为这很不幸,我应该始终记得添加
mapToDouble
:(@ZhekaKozlov只使用DoubleStream
。因此,为了提高性能,他们牺牲了正确性。处理长时间溢出将花费太多。IntStream
行为正常,因为由于返回了optionalduble
,因此总和被转换为double
。在不超过Double.MIN\u VALUE
@JacobG.InLongStream
中的和也被转换为Double
,但没有明确说明。注意Double n=-6004296286240039273L;
编译;不需要任何转换。@JacobG我认为您完全没有抓住要点。这与int-to-Double转换无关(而且是双倍的)。这是关于为求和值的累加选择正确的类型。
double average = LongStream
.of(-4480186093928204294L, -1340542863544260591L, -6004296286240039273L)
.mapToDouble(x -> x)
.average()
.getAsDouble();
-3.9416750812375014E18
IntStream
.of(-1282256274, -1645263673, -1461061809)
.average()