Browse Source

init

tags/v1.1.0
Stephen McQuay 6 years ago
commit
e7e174530e
3 changed files with 103 additions and 0 deletions
  1. +2
    -0
      .hgignore
  2. +56
    -0
      ostat.go
  3. +45
    -0
      ostat_test.go

+ 2
- 0
.hgignore View File

@@ -0,0 +1,2 @@
tags
.*.swp

+ 56
- 0
ostat.go View 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
- 0
ostat_test.go View 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…
Cancel
Save