浮動小数点正数のかなり長いリストがあります(std::vector<float>
、サイズ〜1000)。番号は降順でソートされます。順序に従ってそれらを合計すると:
for (auto v : vec) { sum += v; }
ベクトルの終わり近くでsum
はv
よりはるかに大きくなるため、数値の安定性の問題が発生する可能性があると思います。最も簡単な解決策は、ベクトルを逆の順序でトラバースすることです。私の質問は、前向きの場合と同様に効率的ですか?キャッシュが不足しますか?
他のスマートなソリューションはありますか?
数値の安定性が正確さを意味する場合、はい、正確さの問題が発生する可能性があります。最大値と最小値の比率、および結果を正確にするための要件によっては、これが問題になる場合と問題にならない場合があります。
高精度が必要な場合は、 Kahan summation を検討してください。これは、誤差補正に追加の浮動小数点を使用します。 ペアワイズ総和 もあります。
精度と時間のトレードオフの詳細な分析については、 この記事 を参照してください。
C++ 17の更新:
他の回答のいくつかはstd::accumulate
。 C++ 17以降、アルゴリズムの並列化を可能にする 実行ポリシー があります。
例えば
#include <vector>
#include <execution>
#include <iostream>
#include <numeric>
int main()
{
std::vector<double> input{0.1, 0.9, 0.2, 0.8, 0.3, 0.7, 0.4, 0.6, 0.5};
double reduceResult = std::reduce(std::execution::par, std::begin(input), std::end(input));
std:: cout << "reduceResult " << reduceResult << '\n';
}
これにより、非決定論的な丸めエラーを犠牲にして、大規模なデータセットの集計が速くなります(ユーザーがスレッドのパーティション分割を判断できないと想定しています)。