Подтвердить что ты не робот

Сортировка (поток) удваивается по абсолютной величине

У меня есть ряд двойных значений, которые я хочу суммировать и получить максимальное значение. DoubleStream.summaryStatistics() звучит идеально для этого. Метод getSum() имеет примечание API, напоминающее мне то, что я узнал на одном из моих курсов по информатике: стабильность проблемы суммирования имеет тенденцию быть лучше, если значения сортируются по их абсолютным значениям. Однако DoubleStream не позволяет мне указывать используемый компаратор, он просто будет использовать Double.compareTo, если я вызову sorted() в потоке.

Таким образом, я собрал значения в final Stream.Builder<Double> values = Stream.builder(); и вызвал

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

Тем не менее, это выглядит несколько длинным, и я предпочел бы использовать DoubleStream.Builder вместо генератора. Я что-то пропустил или действительно должен использовать коробчатую версию потока, чтобы указать компаратора?

4b9b3361

Ответ 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();

Однако, поскольку суммирование Кахана используется внутри страны, разница не должна быть значительной. В большинстве приложений несортированный вход даст хорошую результирующую точность. Конечно, вы должны протестировать самостоятельно, если несортированное суммирование удовлетворительно для вашей конкретной задачи.