sum
и sumCompensation
используются для уменьшения ошибки регулярного суммирования с плавающей запятой.
simpleSum
содержит простую сумму (полученную путем применения simpleSum += value;
к каждому добавленному значению) и используется для не конечных сумм.
Детали реализации объясняют, что:
private double sum;
private double sumCompensation; // Low order bits of sum
private double simpleSum; // Used to compute right sum for non-finite inputs
Вот как вычисляются sum
и sumCompensation
:
/**
* Incorporate a new double value using Kahan summation /
* compensated summation.
*/
private void sumWithCompensation(double value) {
double tmp = value - sumCompensation;
double velvel = sum + tmp; // Little wolf of rounding error
sumCompensation = (velvel - sum) - tmp;
sum = velvel;
}
Вы можете увидеть, как они используются в getSum()
:
public final double getSum() {
// Better error bounds to add both terms as the final sum
double tmp = sum + sumCompensation;
if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
// If the compensated sum is spuriously NaN from
// accumulating one or more same-signed infinite values,
// return the correctly-signed infinity stored in
// simpleSum.
return simpleSum;
else
return tmp;
}
.Javadoc getSum()
не требует какой-либо конкретной реализации, но допускает реализации, которые уменьшают границу ошибки:
Значение суммы с плавающей запятой является функцией обоих входных значений, а такжекак порядок операций сложения.Порядок операций сложения этого метода намеренно не определен, чтобы обеспечить гибкость реализации для повышения скорости и точности вычисляемого результата.В частности, этот метод может быть реализован с использованием компенсированного суммирования или другого метода для уменьшения границы ошибки в числовой сумме по сравнению с простым суммированием двойных значений.