yipo
8/17/2015 - 6:48 AM

(Simple) Incremental Statistics

(Simple) Incremental Statistics

#include "inc_stats.hpp"
#include <assert.h>

void test_case()
{
    inc_stats<double, 3> stats;

    stats.in(5.5);
    stats.in(6.6);

    assert(stats.min() == 5.5);
    assert(stats.max() == 6.6);

    stats.in(1.0);
    stats.in(8.0);
    stats.in(3.0);

    assert(stats.min() == 1.0);
    assert(stats.max() == 8.0);

    assert(stats.count() == 5);

    double avg = (1.0 + 8.0 + 3.0) / 3;
    assert(abs(stats.avg() - avg) < 0.001);
}

int main()
{
    test_case();
    return 0;
}

#pragma once

#include <algorithm>
#include <deque>

template<typename T, size_t SUM_COUNT = 0>
class inc_stats
{
    size_t m_cou;
    T m_min, m_max;

    T m_sum;
    std::deque<T> m_que;

public:
    inc_stats() : m_cou(0), m_min(0), m_max(0), m_sum(0)
    {
    }

    void in(T value)
    {
        if (m_cou > 0)
        {
            m_min = std::min(m_min, value);
            m_max = std::max(m_max, value);
        }
        else
        {
            m_min = m_max = value;
        }
        m_cou++;

        m_sum += value;

        if (SUM_COUNT > 0)
        {
            m_que.push_back(value);

            if (m_que.size() > SUM_COUNT)
            {
                m_sum -= m_que.front();
                m_que.pop_front();
            }
        }
    }

    size_t count() const
    {
        return m_cou;
    }

    T min() const
    {
        return m_min;
    }

    T max() const
    {
        return m_max;
    }

    T avg() const
    {
        size_t cou = (SUM_COUNT > 0) ? m_que.size() : m_cou;
        return (cou > 0) ? m_sum / cou : 0;
    }
};


project(inc_stats)
add_executable(${PROJECT_NAME} inc_stats.hpp inc_stats_test.cpp)
@ECHO OFF
CD /D %~dp0

PATH ^
%ProgramFiles%\CMake\bin;^
%ProgramFiles(x86)%\CMake\bin

IF NOT EXIST build MKDIR build
CD build

cmake %* ..
PAUSE