Cumulative standard deviation: Difference between revisions
(smalltalk) |
m (→{{header|Smalltalk}}: added protection for div by 0) |
||
Line 74: | Line 74: | ||
] |
] |
||
count [ ^ num ] |
count [ ^ num ] |
||
mean [ ^ sum / num ] |
mean [ num>0 ifTrue: [^ sum / num] ifFalse: [ ^ 0.0 ] ] |
||
variance [ |m| m := self mean. |
variance [ |m| m := self mean. |
||
^ (sum2/num) - (m*m) |
num>0 ifTrue: [^ (sum2/num) - (m*m) ] ifFalse: [ ^ 0.0 ] |
||
] |
] |
||
stddev [ ^ (self variance) sqrt ] |
stddev [ ^ (self variance) sqrt ] |
Revision as of 15:11, 16 June 2009
You are encouraged to solve this task according to the task description, using any language you may know.
Write a stateful function, class, generator or coroutine that takes a series of floating point numbers, one at a time, and returns the running standard deviation of the series. The task implementation should use the most natural programming style of those listed for the function in the implementation language; the task must state which is being used. Do not apply Bessel's Correction; the returned standard deviation should always be computed as if the sample seen so far is the entire population.
Use this to compute the standard deviation of the demonstration set:
C
Of course this function is not thread-safe nor it can be used to compute the standard deviation just for a set of values per time.
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <math.h>
enum Action { VALUE, STDDEV, MEAN, VAR, COUNT, RESET }; double stat_object(double v, enum Action action) {
static double sum = 0.0; static double sum2 = 0.0; static size_t num = 0;
double m;
switch(action) { case VALUE: num++; sum += v; sum2 += v*v; return stat_object(0.0, STDDEV); case STDDEV: return sqrt(stat_object(0.0, VAR)); case MEAN: return (num>0) ? sum/(double)num : 0.0; case VAR: m = stat_object(0.0, MEAN); return (num>0) ? (sum2/(double)num - m*m) : 0.0; case COUNT: return num; case RESET: sum = sum2 = 0.0; num = 0; return 0.0; }
}</lang>
<lang c>double v[] = { 2,4,4,4,5,5,7,9 };
int main() {
int i; double sd;
for(i=0; i < sizeof(v)/sizeof(double) ; i++) sd = stat_object(v[i], VALUE);
printf("standard dev = %lf\n", sd);
return 0;
}</lang>
Smalltalk
<lang smalltalk>Object subclass: SDAccum [
|sum sum2 num| SDAccum class >> new [ |o| o := super basicNew. ^ o init. ] init [ sum := 0. sum2 := 0. num := 0 ] value: aValue [ sum := sum + aValue. sum2 := sum2 + ( aValue * aValue ). num := num + 1. ^ self stddev ] count [ ^ num ] mean [ num>0 ifTrue: [^ sum / num] ifFalse: [ ^ 0.0 ] ] variance [ |m| m := self mean. num>0 ifTrue: [^ (sum2/num) - (m*m) ] ifFalse: [ ^ 0.0 ] ] stddev [ ^ (self variance) sqrt ]
].</lang>
<lang smalltalk>|sdacc sd| sdacc := SDAccum new.
- ( 2 4 4 4 5 5 7 9 ) do: [ :v | sd := sdacc value: v ].
('std dev = %1' % { sd }) displayNl.</lang>
Tcl
With a Class
<lang tcl>oo::class create SDAccum {
variable sum sum2 num constructor {} { set sum 0.0 set sum2 0.0 set num 0 } method value {x} { set sum2 [expr {$sum2 + $x**2}] set sum [expr {$sum + $x}] incr num return [my stddev] } method count {} { return $num } method mean {} { expr {$sum / double($num)} } method variance {} { expr {($sum2 - double($num)*[my mean]**2)/double($num)} } method stddev {} { expr {sqrt([my variance])} }
}
- Demonstration
set sdacc [SDAccum new] foreach val {2 4 4 4 5 5 7 9} {
set sd [$sdacc value $val]
} puts "the standard deviation is: $sd"</lang> which produces the output:
the standard deviation is: 2.0