Improve calc_mean function

A problem with using std::accumulate to calculate the mean is that small numbers get rounded down to zero when dealing with floating point numbers. This is solved by implementing the Kahan summation algorithm (https://en.wikipedia.org/wiki/Kahan_summation_algorithm).
This commit is contained in:
sukibaby
2024-05-26 15:54:00 -07:00
committed by teejusb
parent 6f86f3eae5
commit c2ac89dcb6
+14 -2
View File
@@ -1190,9 +1190,21 @@ void SortRStringArray( std::vector<RString> &arrayRStrings, const bool bSortAsce
bSortAscending?CompareRStringsAsc:CompareRStringsDesc );
}
float calc_mean( const float *pStart, const float *pEnd )
float calc_mean(const float* pStart, const float* pEnd)
{
return std::accumulate( pStart, pEnd, 0.f ) / std::distance( pStart, pEnd );
/* The Kahan summation algorithm is used here to prevent
* situations where the low order bits may be lost.
* https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
float sum = 0.0f;
float c = 0.0f;
for (const float* p = pStart; p != pEnd; ++p)
{
float y = *p - c;
float t = sum + y;
c = (t - sum) - y;
sum = t;
}
return sum / (pEnd - pStart);
}
float calc_stddev( const float *pStart, const float *pEnd, bool bSample )