init
This commit is contained in:
commit
e7e174530e
56
ostat.go
Normal file
56
ostat.go
Normal file
@ -0,0 +1,56 @@
|
||||
package ostat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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
|
||||
}
|
||||
|
||||
func NewOnlineStat() *OnlineStat {
|
||||
return &OnlineStat{
|
||||
Min: math.Inf(1),
|
||||
Max: math.Inf(-1),
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (os *OnlineStat) Mean() (float64, error) {
|
||||
if os.n == 0 {
|
||||
return 0.0, errors.New("no data")
|
||||
}
|
||||
return os.mean, nil
|
||||
}
|
||||
|
||||
func (os *OnlineStat) Variance() (float64, error) {
|
||||
if os.n == 0 {
|
||||
return 0.0, errors.New("no data")
|
||||
}
|
||||
return os.m2 / float64(os.n-1), nil
|
||||
}
|
||||
|
||||
func (os *OnlineStat) StdDev() (float64, error) {
|
||||
variance, err := os.Variance()
|
||||
return math.Sqrt(variance), err
|
||||
}
|
45
ostat_test.go
Normal file
45
ostat_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package ostat
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInsert(t *testing.T) {
|
||||
os := NewOnlineStat()
|
||||
v := []float64{4, 7, 13, 16}
|
||||
for _, i := range v {
|
||||
os.Push(i)
|
||||
}
|
||||
if os.Min != 4 {
|
||||
t.Errorf("incorrectly calculated min")
|
||||
}
|
||||
if os.Max != 16 {
|
||||
t.Errorf("incorrectly calculated max")
|
||||
}
|
||||
if m, _ := os.Mean(); m != 10.0 {
|
||||
t.Errorf("incorrect mean")
|
||||
}
|
||||
if variance, _ := os.Variance(); variance != 30.0 {
|
||||
t.Errorf("incorrect variance: %f", variance)
|
||||
}
|
||||
if stdev, _ := os.StdDev(); stdev != math.Sqrt(30.0) {
|
||||
t.Errorf("incorrect stdev: %f", stdev)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
os := NewOnlineStat()
|
||||
_, err := os.Mean()
|
||||
if err == nil {
|
||||
t.Errorf("failure to notify the running stat was empty")
|
||||
}
|
||||
_, err = os.Variance()
|
||||
if err == nil {
|
||||
t.Errorf("failure to notify the running stat was empty")
|
||||
}
|
||||
_, err = os.StdDev()
|
||||
if err == nil {
|
||||
t.Errorf("failure to notify the running stat was empty")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user