http://rosettacode.org/wiki/Averages/Simple_moving_average#C.2B.2B
The original rosetta C example shows the usage of variable function arguments. The C++ example shows how to implement a circular buffer. They are confusing and inefficient. My Version shows how to implement a simple moving average using modern c++ techniques.
#include < iostream >
#include < vector >
class SMA {
public:
SMA(int period) : values(period), sum(0.0), idx(0), size(0) {
}
void add(double value) {
const size_t period = values.size();
// here is the magic. Update sum and vector in place
sum = sum - values[idx] + value;
values[idx] = value;
// this implements the circular buffer
idx = (idx+1)%period;
if(size+1 <= period) {
++size;
}
}
double avg() const {
return sum/size;
}
private:
// store the last seen values
std::vector values;
// store the sum. so we dont have to recalculate it every time
double sum;
// the next element in the buffer we can override
int idx;
// ho many values was allready inserted. This is usually the same as the given periodb
size_t size;
};
int main() {
SMA foo(3);
SMA bar(5);
std::vector data = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
for(auto &val : data) {
foo.add(val);
std::cout << "Added " << val << " avg: " << foo.avg() << std::endl;
}
std::cout << std::endl;
for(auto &val : data) {
bar.add(val);
std::cout << "Added " << val << " avg: " << bar.avg() << std::endl;
}
return 0;
}