2013-12-28 23:56:48 -08:00
|
|
|
package ostat
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
)
|
|
|
|
|
|
|
|
// from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
|
|
|
|
|
|
|
|
type OnlineStat struct {
|
|
|
|
n int64
|
|
|
|
mean float64
|
|
|
|
m2 float64
|
|
|
|
Max float64
|
|
|
|
Min float64
|
2013-12-29 00:48:20 -08:00
|
|
|
typ int64
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
|
|
|
|
2013-12-29 00:48:20 -08:00
|
|
|
func NewSampleStat() *OnlineStat {
|
2013-12-28 23:56:48 -08:00
|
|
|
return &OnlineStat{
|
|
|
|
Min: math.Inf(1),
|
|
|
|
Max: math.Inf(-1),
|
2013-12-29 00:48:20 -08:00
|
|
|
typ: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPopulationStat() *OnlineStat {
|
|
|
|
return &OnlineStat{
|
|
|
|
Min: math.Inf(1),
|
|
|
|
Max: math.Inf(-1),
|
|
|
|
typ: 0,
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (os *OnlineStat) Push(v float64) {
|
|
|
|
os.n += 1
|
|
|
|
if v < os.Min {
|
|
|
|
os.Min = v
|
|
|
|
}
|
|
|
|
if v > os.Max {
|
|
|
|
os.Max = v
|
|
|
|
}
|
|
|
|
|
|
|
|
delta := v - os.mean
|
|
|
|
os.mean = os.mean + delta/float64(os.n)
|
|
|
|
os.m2 = os.m2 + delta*(v-os.mean)
|
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
func (os *OnlineStat) Mean() float64 {
|
2013-12-28 23:56:48 -08:00
|
|
|
if os.n == 0 {
|
2014-01-01 10:46:34 -08:00
|
|
|
return 0.0
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
return os.mean
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
func (os *OnlineStat) Variance() float64 {
|
2013-12-28 23:56:48 -08:00
|
|
|
if os.n == 0 {
|
2014-01-01 10:46:34 -08:00
|
|
|
return 0.0
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
return os.m2 / float64(os.n-os.typ)
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
func (os *OnlineStat) StdDev() float64 {
|
|
|
|
return math.Sqrt(os.Variance())
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|