간단한 통계 클래스 구현하기

//------------------------------+---------------------------------------------------------------

#include <cmath>
#include <initializer_list>

#define CRE

using	u32			        	= unsigned int;

//------------------------------+---------------------------------------------------------------

class                           STATS
{
private:
    double                      single_sum, square_sum;
    u32                         count;

public:
    auto&                       operator!()
    {
        single_sum = square_sum = 0.;
        count = 0;
        return  *this;
    }

    CRE                         STATS()
    {
        !*this;
    }
    template< class T >
    CRE                         STATS( const T* data, const u32 count )
    {
        assign( data, count );
    }
    template< class T >
    CRE                         STATS( const std::initializer_list< T > list )
    {
		assign( list );
    }

    auto                        size() const
    {
        return  count;
    }

	template< class T >
    auto&                       operator<<( T datum )
    {
        square_sum += (double)datum * datum;
        single_sum += datum;
        count++;
        return  *this;
    }

	template< class T >
    auto&                       assign( const T* data, const u32 count )
    {
        for( !*this; size() < count; *this << data[ size() ] );
        return  *this;
    }

    template< class T >
    auto&                       assign( const std::initializer_list< T > list )
    {
		!*this;
		for( const auto item : list )
			*this << item;
		return	*this;
    }

    auto                        average() const
    {
        return  single_sum / count;
    }

    auto                        variance() const
    {
        return  ( square_sum - single_sum * single_sum / count ) / ( count - 1 );
    }

    auto                        stdev() const
    {
        return  std::sqrt( variance() );
    }

    auto                        sum() const
    {
        return  single_sum;
    }
};
//------------------------------+---------------------------------------------------------------

합, 평균, 표준편차, 분산을 제공해주는 함수입니다.

장점을 꼽으라면,

1. 추가적인 메모리를 사용하지 않습니다.
2. 이벤트로 넘어오는 비동기적 입력 스트림에 대응하기 좋습니다.
3. 조금 메모리를 사용하게 수정하면
   구간합 / 구간평균 / 구간분산 / 구간표준편차를 구하게 됩니다.
4. 간단해서 별로 유지보수할 여지가 없습니다. ( 하지만 0으로 나누면 어떨까 )

예제

    // 배열로 동작시키기
    int data[] { 3, 2, 1 };
    printf( "%lf\n", STATS( data, sizeof data / sizeof *data ).stdev() );

    // 생성 후 하나씩 추가해서 별도의 메모리 없이 동작시키기1
    STATS   stats;
    for( int i = 0; i < 1000; ++i )
        stats << i;
    printf( "%lf\n", stats.average() );

    // 초기화 후 하나씩 추가해서 별도의 메모리 없이 동작시키기2
    printf( "%lf\n", ( !stats << 1 << 2 << 3 ).variance() );

    // initializer list
    printf( "%lf\n", STATS( { 1, 2, 3 } ).sum() );

결과

1.000000
499.500000
1.000000
6.000000
2 Likes

!연산자 오버로딩 첫째줄에
sum = square_sum = 0.; 이 아니라
single_ sum = square_sum = 0.; 인것같네요.

맞음 네이밍 바꿨는데 안따라왔네유

#define CRE

옛날 글 읽다가 궁금해졌는데, 이건 무슨 의미인가요?

CRE를 정의하되 내용은 아무것도 없는걸로.

생성자마다 붙어있으니 생성자임을 나타내려고 하신 것 같은데… 생성자는 Constructor 아닌가…

CON 은 다른곳에서 많이쓰고 CRE는 타이핑 하기도 편함
에디터에서 자동으로 왼쪽으로 붙어버리는 경우도 막아주기 위한 줄세우기용

그렇다고 CSTR 이 고상한 취향 같진 않음

CS나 CR… 은 좀 이상하려나요?

CTOR ㅋ_ㅋ

그거 제안하려고 했다가 생각해보니 이동거리가 너무 깁니다.

맞다. CTOR 도 많이들 쓰죠. ㅋㅋ 네글자 싫음 ㅠㅠ

NEW? 같은걸 끼얹나? 자바와 닮게?

class some_class
{
    public: some_class() default;
};

:thinking:

snake 좋군~

  !*this;
   assign( data, count );
   assign( list );

constructor에서 함수 호출하면 함수의 반환값이 리턴되는 거였나요??
stackoverflow에서도 constructor에서는 return이 안된다고 했던거로 기억하는데요.?! 실제로 해보니까 되네요.

eax r0 같은 반환 레지스터 값을 안 건드리고 그곳을 읽는다면 리턴이 되는 착각을 일으킬 수 있고
언어에서 게런티 할 수 있는건 아니죠

6.6.3 The return statement
2 A return statement without an expression can be used only in functions that do not return a value, that is, a function with the return type void, a constructor (12.1), or a destructor (12.4). A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function.

리턴 statement는 표준입니당. 그런데 값을 리턴하려고하면 컴파일에러가 뜨지않나여??

return !*this; 하면 컴파일 에러겠죠? !*this만 썼을때 리턴밸류는 어차피 컴파일러님께서 최적화해줄거고ㅎㅎ

push_backvoid인 모 컨테이너가 떠오르네요. 괘씸하여라…

이게 어떤 의미인가요??

위에 코드에 operator! 정의되어 있잖읍니까