C++Guns – RoboBlog blogging the bot

26.02.2015

rosettacode - Simple moving variance

Filed under: Allgemein — Tags: , — Thomas @ 11:02

As mentioned in my earlier post original C++ rosettacode sucks.
Here is my example for a simple moving variance and standard deviation. One has to add only a few lines of code:


in add()
...
    sum2 = sum2 - oldValue*oldValue + value*value;
...

double var() const {
    return sum2/size - avg()*avg();
}

double std() const {
    return std::sqrt(var());
}
Data1 Period 3
Added 1 avg:        1 var:        0 std: 0
Added 2 avg:      1.5 var:     0.25 std: 0.5
Added 3 avg:        2 var: 0.666667 std: 0.816497
Added 4 avg:        3 var: 0.666667 std: 0.816497
Added 5 avg:        4 var: 0.666667 std: 0.816497
Added 5 avg:  4.66667 var: 0.222222 std: 0.471405
Added 4 avg:  4.66667 var: 0.222222 std: 0.471405
Added 3 avg:        4 var: 0.666667 std: 0.816497
Added 2 avg:        3 var: 0.666667 std: 0.816497
Added 1 avg:        2 var: 0.666667 std: 0.816497

Data2 Period 8
Added 2 avg:        2 var:        0 std: 0
Added 4 avg:        3 var:        1 std: 1
Added 4 avg:  3.33333 var: 0.888889 std: 0.942809
Added 4 avg:      3.5 var:     0.75 std: 0.866025
Added 5 avg:      3.8 var:     0.96 std: 0.979796
Added 5 avg:        4 var:        1 std: 1
Added 7 avg:  4.42857 var:  1.95918 std: 1.39971
Added 9 avg:        5 var:        4 std: 2

ToDo: add Skewness and Kurtosis

18.02.2015

rosettacode - Simple moving average

Filed under: Allgemein — Tags: , , — Thomas @ 12:02

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;
}


Powered by WordPress