Minimize floating point error when adding multiple floating point variables

*爱你&永不变心* 提交于 2019-12-04 07:02:20

One of the standard ways of approaching this issue is the Kahan summation algorithm. This algorithm reduces your worst-case error to being dependent upon your floating point precision rather than growing proportional to the length of your vector (and does it in O(n) time, albeit with more calculations per iteration).

Kahan summation will likely outperform your current sumDoubles due to your sorting every call, and will additionally improve pairwise summation's error growth of O(log n) to O(1). This said, if the sort is unnecessary, pairwise summation will likely outperform Kahan summation (due to the additional per-iteration math involved) with what may be (for your circumstances) minimal error growth.

You're supposed to sort by absolute value. Currently, -100000000.0 sorts before 0.000000001. The idea of sorting is that you can then add terms of the same magnitude. Adding -100000000.0 and +100000000.0 if perfectly fine, so they should sort close together, but adding -100000000.0 and 0.000000001 gets you into problems with accuracy.

A second problem with your algorithm is that your evaluation order is pretty horrible. As you correctly note, you've got a tree structure, but even then you can evaluate the subexpressions in any order. The most efficient order for memory access would be to add [0] and [1], then [2] and [3], and then [0] and [2] before adding [4] and [5]. The reason is simple: you've got [0] and [2] still in cache, and their values will change. So don't write the intermediate values back to main memory just to read and modify them later. (In tree terms, that's DFS versus BFS evaluation)

For the same cache efficiency reasons, I'd also modify the location where you'd store the interim results. Sure, store [0] + [1] in [0]. But after that, [1] is not needed anymore. Store [2] + [3] in [1]. Now, add [0] and [1] again to get the sum of [0]..[3] stored in [0].

To summarize: add intermediate results together as soon as possible, to reduce the number of them, and store them in contiguous memory at the start of the array instead of scattered all around.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!