java - 为什么 IntStream.average() 总是返回正确的结果而 LongStream.average() 有时却不能?

标签 java java-8 java-stream

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/

相关文章:

java-8 - JavaFX : ObsevableMap keySet as an ObservableSet

java - 将嵌套的 foreach 重构为 Java 8 流

Java 并行流 : how to wait for threads for a parallel stream to finish?

java - 使用 Java 8 Streams 从列表中仅获取所需的对象

java - 调用服务时连接超时 VS 读取超时

java - 使用 StAx 解析 XML 文件时出错

java - 为什么某些对象方法不能从默认方法调用?

java - 如何使用 Java 将文档上传到 SharePoint?

java - VTD-XML 大数据 xPathExpression 不适用于 namespace

具有各种操作数的 Java lambda 表达式