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
。在不超过的情况下,不会溢出/下溢e> Double.MAX\u VALUE/
Double.MIN\u VALUE
@JacobG.In
LongStream
中的和也被转换为
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()