goj*_*oji 39 c++ boost moving-average
我知道这是可以通过提升实现的:
使用boost :: accumulators,如何重置滚动窗口大小,是否保留了额外的历史记录?
但我真的想避免使用提升.我用谷歌搜索,没有找到任何合适或可读的例子.
基本上我想使用最新的1000个数字作为数据样本来跟踪正在进行的浮点数流的移动平均值.
实现这一目标的最简单方法是什么?
我尝试使用圆形阵列,指数移动平均线和更简单的移动平均线,发现圆形阵列的结果最适合我的需要.
ste*_*eha 79
如果您的需求很简单,您可以尝试使用指数移动平均线.
http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
简而言之,您创建了一个累加器变量,并且当您的代码查看每个示例时,代码会使用新值更新累加器.你选择一个介于0和1之间的常量"alpha",并计算:
accumulator = (alpha * new_value) + (1.0 - alpha) * accumulator
Run Code Online (Sandbox Code Playgroud)
您只需要找到"alpha"值,其中给定样本的效果仅持续约1000个样本.
嗯,我现在还不确定它是否适合你,现在我把它放在这里.问题是,对于指数移动平均线而言,1000是一个相当长的窗口; 我不确定是否有一个alpha会在过去的1000个数字上传播平均值,而在浮点计算中没有下溢.但是如果你想要一个较小的平均值,比如30个数左右,这是一个非常简单快捷的方法.
Kar*_*han 19
你只需要一个1000个元素的圆形数组,在这里你可以将元素添加到前一个元素并存储它......它变成了一个增加的总和,你可以随时得到任意两对元素之和,并除以数字它们之间的元素,以产生平均值.
Ton*_*roy 14
基本上我想使用最新的1000个数字作为数据样本来跟踪正在进行的浮点数流的移动平均值.
请注意,下面更新total_ as元素作为添加/替换,避免代价高昂的O(N)遍历来计算平均值所需的总和 - 按需.
template <typename T, typename Total, size_t N>
class Moving_Average
{
public:
void operator()(T sample)
{
if (num_samples_ < N)
{
samples_[num_samples_++] = sample;
total_ += sample;
}
else
{
T& oldest = samples_[num_samples_++ % N];
total_ += sample - oldest;
oldest = sample;
}
}
operator double() const { return total_ / std::min(num_samples_, N); }
private:
T samples_[N];
size_t num_samples_{0};
Total total_{0};
};
Run Code Online (Sandbox Code Playgroud)
total_
由不同的参数从Total
支持例如使用T
共计1000个时long long
S,一个long
用于int
S,或一个char
到总double
秒.
这有点有缺陷,float
可能会过去num_samples_
- 如果你关心你可以使用a num_samples_
,或者使用额外的bool数据成员来记录容器第一次填充时在数组周围循环num_samples_(最好重命名为无关紧要的东西,如" pos
") .
jxh*_*jxh 14
您可以通过在输入流上应用加权平均值来估算滚动平均值.
template <unsigned N>
double approxRollingAverage (double avg, double input) {
avg -= avg/N;
avg += input/N;
return avg;
}
Run Code Online (Sandbox Code Playgroud)
这样,您就不需要维护1000个桶.但是,这是一个近似值,因此它的值与真正的滚动平均值不完全匹配.
编辑:刚注意到@ steveha的帖子.这相当于指数移动平均线,alpha为1/N(在这种情况下,我将N取为1000来模拟1000个桶).