|
1 | 1 | //
|
2 | 2 | // FILE: Statistic.cpp
|
3 |
| -// AUTHOR: Rob dot Tillaart at gmail dot com |
| 3 | +// AUTHOR: Rob dot Tillaart at gmail dot com |
4 | 4 | // modified at 0.3 by Gil Ross at physics dot org
|
5 |
| -// VERSION: see STATISTIC_LIB_VERSION in .h |
| 5 | +// VERSION: 0.3.3 |
6 | 6 | // PURPOSE: Recursive statistical library for Arduino
|
7 | 7 | //
|
8 | 8 | // NOTE: 2011-01-07 Gill Ross
|
9 | 9 | // Rob Tillaart's Statistic library uses one-pass of the data (allowing
|
10 | 10 | // each value to be discarded), but expands the Sum of Squares Differences to
|
11 | 11 | // difference the Sum of Squares and the Average Squared. This is susceptible
|
12 |
| -// to bit length precision errors with the float type (only 5 or 6 digits |
| 12 | +// to bit length precision errors with the float type (only 5 or 6 digits |
13 | 13 | // absolute precision) so for long runs and high ratios of
|
14 |
| -// the average value to standard deviation the estimate of the |
| 14 | +// the average value to standard deviation the estimate of the |
15 | 15 | // standard error (deviation) becomes the difference of two large
|
16 | 16 | // numbers and will tend to zero.
|
17 | 17 | //
|
18 | 18 | // For small numbers of iterations and small Average/SE th original code is
|
19 | 19 | // likely to work fine.
|
20 |
| -// It should also be recognised that for very large samples, questions |
| 20 | +// It should also be recognised that for very large samples, questions |
21 | 21 | // of stability of the sample assume greater importance than the
|
22 | 22 | // correctness of the asymptotic estimators.
|
23 | 23 | //
|
24 | 24 | // This recursive algorithm, which takes slightly more computation per
|
25 | 25 | // iteration is numerically stable.
|
26 | 26 | // It updates the number, mean, max, min and SumOfSquaresDiff each step to
|
27 |
| -// deliver max min average, population standard error (standard deviation) and |
| 27 | +// deliver max min average, population standard error (standard deviation) and |
28 | 28 | // unbiassed SE.
|
29 | 29 | // -------------
|
30 | 30 | //
|
|
34 | 34 | // 0.2.01 - 2010-10-30
|
35 | 35 | // added minimim, maximum, unbiased stdev,
|
36 | 36 | // changed counter to long -> int overflows @32K samples
|
37 |
| -// 0.3 - 2011-01-07 |
| 37 | +// 0.3 - 2011-01-07 |
38 | 38 | // branched from 0.2.01 version of Rob Tillaart's code
|
39 | 39 | // 0.3.1 - minor edits
|
40 | 40 | // 0.3.2 - 2012-11-10
|
41 |
| -// minor edits |
| 41 | +// minor edits |
42 | 42 | // changed count -> unsigned long allows for 2^32 samples
|
43 | 43 | // added variance()
|
| 44 | +// 0.3.3 - 2015-03-07 |
| 45 | +// float -> double to support ARM (compiles) |
| 46 | +// moved count() sum() min() max() to .h; for optimizing compiler |
44 | 47 | //
|
45 | 48 | // Released to the public domain
|
46 | 49 | //
|
|
49 | 52 |
|
50 | 53 | Statistic::Statistic()
|
51 | 54 | {
|
52 |
| -clear(); |
| 55 | + clear(); |
53 | 56 | }
|
54 | 57 |
|
55 | 58 | // resets all counters
|
56 | 59 | void Statistic::clear()
|
57 |
| -{ |
58 |
| -_cnt = 0; |
59 |
| -_sum = 0.0; |
60 |
| -_min = 0.0; |
61 |
| -_max = 0.0; |
| 60 | +{ |
| 61 | + _cnt = 0; |
| 62 | + _sum = 0.0; |
| 63 | + _min = 0.0; |
| 64 | + _max = 0.0; |
62 | 65 | #ifdef STAT_USE_STDEV
|
63 |
| -_ssqdif = 0.0; // not _ssq but sum of square differences |
64 |
| - // which is SUM(from i = 1 to N) of |
65 |
| - // (f(i)-_ave_N)**2 |
| 66 | + _ssqdif = 0.0; // not _ssq but sum of square differences |
| 67 | + // which is SUM(from i = 1 to N) of |
| 68 | + // (f(i)-_ave_N)**2 |
66 | 69 | #endif
|
67 | 70 | }
|
68 | 71 |
|
69 | 72 | // adds a new value to the data-set
|
70 |
| -void Statistic::add(float f) |
| 73 | +void Statistic::add(double value) |
71 | 74 | {
|
72 |
| -if (_cnt == 0) |
73 |
| -{ |
74 |
| -_min = f; |
75 |
| -_max = f; |
76 |
| -} else { |
77 |
| -if (f < _min) _min = f; |
78 |
| -if (f > _max) _max = f; |
| 75 | + if (_cnt == 0) |
| 76 | + { |
| 77 | + _min = value; |
| 78 | + _max = value; |
| 79 | + } else { |
| 80 | + if (value < _min) _min = value; |
| 81 | + else if (value > _max) _max = value; |
79 | 82 | }
|
80 |
| -_sum += f; |
81 |
| -_cnt++; |
82 |
| -
|
83 |
| -#ifdef STAT_USE_STDEV |
84 |
| - if (_cnt >1) |
85 |
| -{ |
86 |
| - _store = (_sum / _cnt - f); |
| 83 | + _sum += value; |
| 84 | + _cnt++; |
| 85 | + |
| 86 | +#ifdef STAT_USE_STDEV |
| 87 | + if (_cnt > 1) |
| 88 | + { |
| 89 | + _store = (_sum / _cnt - value); |
87 | 90 | _ssqdif = _ssqdif + _cnt * _store * _store / (_cnt-1);
|
88 |
| - } |
| 91 | + } |
89 | 92 | #endif
|
90 | 93 | }
|
91 | 94 |
|
92 |
| -// returns the number of values added |
93 |
| -unsigned long Statistic::count() |
94 |
| -{ |
95 |
| -return _cnt; |
96 |
| -} |
97 |
| - |
98 | 95 | // returns the average of the data-set added sofar
|
99 |
| -float Statistic::average() |
100 |
| -{ |
101 |
| -if (_cnt == 0) return NAN; // original code returned 0 |
102 |
| -return _sum / _cnt; |
103 |
| -} |
104 |
| - |
105 |
| -// returns the sum of the data-set (0 if no values added) |
106 |
| -float Statistic::sum() |
| 96 | +double Statistic::average() |
107 | 97 | {
|
108 |
| -return _sum; |
| 98 | + if (_cnt == 0) return NAN; // original code returned 0 |
| 99 | + return _sum / _cnt; |
109 | 100 | }
|
110 | 101 |
|
111 |
| -// returns the sum of the data-set (0 if no values added) |
112 |
| -float Statistic::minimum() |
113 |
| -{ |
114 |
| -return _min; |
115 |
| -} |
116 |
| - |
117 |
| -// returns the sum of the data-set (0 if no values added) |
118 |
| -float Statistic::maximum() |
119 |
| -{ |
120 |
| -return _max; |
121 |
| -} |
122 |
| - |
123 |
| - |
124 | 102 | // Population standard deviation = s = sqrt [ S ( Xi - µ )2 / N ]
|
125 | 103 | // http://www.suite101.com/content/how-is-standard-deviation-used-a99084
|
126 |
| -#ifdef STAT_USE_STDEV |
| 104 | +#ifdef STAT_USE_STDEV |
127 | 105 |
|
128 |
| -float Statistic::variance() |
| 106 | +double Statistic::variance() |
129 | 107 | {
|
130 |
| -if (_cnt == 0) return NAN; // otherwise DIV0 error |
131 |
| -return _ssqdif / _cnt; |
| 108 | + if (_cnt == 0) return NAN; // otherwise DIV0 error |
| 109 | + return _ssqdif / _cnt; |
132 | 110 | }
|
133 | 111 |
|
134 |
| -float Statistic::pop_stdev() |
| 112 | +double Statistic::pop_stdev() |
135 | 113 | {
|
136 |
| -if (_cnt == 0) return NAN; // otherwise DIV0 error |
137 |
| -return sqrt( _ssqdif / _cnt); |
| 114 | + if (_cnt == 0) return NAN; // otherwise DIV0 error |
| 115 | + return sqrt( _ssqdif / _cnt); |
138 | 116 | }
|
139 | 117 |
|
140 |
| -float Statistic::unbiased_stdev() |
| 118 | +double Statistic::unbiased_stdev() |
141 | 119 | {
|
142 |
| -if (_cnt < 2) return NAN; // otherwise DIV0 error |
143 |
| -return sqrt( _ssqdif / (_cnt - 1)); |
| 120 | + if (_cnt < 2) return NAN; // otherwise DIV0 error |
| 121 | + return sqrt( _ssqdif / (_cnt - 1)); |
144 | 122 | }
|
145 | 123 |
|
146 | 124 | #endif
|
|
0 commit comments