排序(流)按绝对星等加倍

2022-09-02 01:35:45

我有一系列双精度值,我想总结一下并得到最大值。听起来非常适合这样。该方法有一个API注释,提醒我在一门计算机科学课程中学到的东西:如果按绝对值对值进行排序,则求和问题的稳定性往往会更好。但是,不让我指定要使用的比较器,它只会在我调用流时使用。DoubleStream.summaryStatistics()getSum()DoubleStreamDouble.compareTosorted()

因此,我将值收集到 a 和调用中final Stream.Builder<Double> values = Stream.builder();

values.build()
    .sorted(Comparator.comparingDouble(Math::abs))
    .mapToDouble(a -> a).summaryStatistics();

然而,这看起来有些冗长,我宁愿使用而不是通用构建器。我是否错过了什么,或者我真的必须使用盒装版本的流才能指定比较器?DoubleStream.Builder


答案 1

原始流没有重载方法,将按自然顺序排序。但是,回到您的根本问题,有一些方法可以提高总和的准确性,而不涉及首先对数据进行排序。sorted

一种这样的算法是Kahan求和算法,它恰好由OpenJDK /Oracle JDK内部使用。

诚然,这是一个实现细节,因此通常的警告适用(非OpenJDK / Oracle JDK或未来的OpenJDK JDK可能会采取替代方法等)。

另请参阅此帖子:应按什么顺序添加浮点数以获得最精确的结果?


答案 2

唯一可能的排序方法是将其装箱/拆箱:DoubleStream

double[] input = //...
DoubleStream.of(input).boxed()
    .sorted(Comparator.comparingDouble(Math::abs))
    .mapToDouble(a -> a).summaryStatistics();

然而,由于Kahan求和是在内部使用的,因此差异应该不是很大。在大多数应用中,未排序的输入将产生良好的精度。当然,您应该自己测试未排序的总和是否适合您的特定任务。


推荐