aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2021-01-23 13:44:24 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2021-01-23 13:44:24 -0500
commit8702a4095f0d86949b69d379f587f4037d6516fd (patch)
tree005d5c2ade491ee2464d67dce92e3341854c3e06
parenta2245a9a1653dc25e899ea8b090d2c6be48b00a3 (diff)
downloadstats-8702a4095f0d86949b69d379f587f4037d6516fd.tar.gz
stats-8702a4095f0d86949b69d379f587f4037d6516fd.tar.xz
Add working tests. Fix issue with min/max.
-rw-r--r--print.go2
-rw-r--r--stats.go19
-rw-r--r--stats_test.go62
3 files changed, 76 insertions, 7 deletions
diff --git a/print.go b/print.go
index 8bdeea3..fea1d7d 100644
--- a/print.go
+++ b/print.go
@@ -14,7 +14,7 @@ func (s *Stats) PrettyStats() string {
Standard Deviation: %.2f
Skewness: %.2f
Kurtosis: %.2f
-`, s.Min, s.Max, s.Mean(), s.Variance(), s.StandardDeviation(), s.Skewness(), s.Kurtosis())
+`, s.Min(), s.Max(), s.Mean(), s.Variance(), s.StandardDeviation(), s.Skewness(), s.Kurtosis())
}
// Returns a string containing all of the data within the struct
diff --git a/stats.go b/stats.go
index 46ddc99..534d24e 100644
--- a/stats.go
+++ b/stats.go
@@ -40,8 +40,7 @@ import (
// several methods are exposed in order to make your life easy
type Stats struct {
n, m1, m2, m3, m4 float64
- Max float64
- Min float64
+ max, min *float64
}
// Zeros out the struct for re-use
@@ -55,11 +54,11 @@ func (s *Stats) Clear() {
func (s *Stats) Push(x float64) {
var delta, delta_n, delta_n2, term1, n1 float64
- if x >= s.Max {
- s.Max = x
+ if s.max == nil || x >= *s.max {
+ s.max = &x
}
- if x <= s.Min {
- s.Min = x
+ if s.min == nil || x <= *s.min {
+ s.min = &x
}
n1 = s.n
@@ -97,3 +96,11 @@ func (s *Stats) Skewness() float64 {
func (s *Stats) Kurtosis() float64 {
return s.n*s.m4/(s.m2*s.m2) - 3
}
+
+func (s *Stats) Min() float64 {
+ return *s.min
+}
+
+func (s *Stats) Max() float64 {
+ return *s.max
+}
diff --git a/stats_test.go b/stats_test.go
new file mode 100644
index 0000000..a101270
--- /dev/null
+++ b/stats_test.go
@@ -0,0 +1,62 @@
+package stats
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+ "testing"
+)
+
+var (
+ datasets [][]float64 = [][]float64{
+ // set 0
+ {
+ 22.90, 28.55, 36.33, 33.71, 26.29, 34.64, 30.14, 34.31,
+ 25.69, 30.09, 28.69, 11.61, 10.68, 24.70, 22.83, 38.08,
+ 24.22, 41.08, 29.70, 26.01, 38.47, 40.25,
+ },
+ // set 1
+ {
+ 15.054, 19.106, 16.926, 16.243, 20.345, 18.615, 15.050,
+ 18.716, 13.691, 18.296, 16.816, 21.415, 20.756, 13.696,
+ 22.679, 16.277, 18.738, 20.271, 20.967, 19.157, 20.338,
+ },
+ }
+ expectedMethodResults map[string][]float64 = map[string][]float64{
+ "Mean": {29.044091, 18.2453333333333},
+ "StandardDeviation": {8.06420820019572, 2.56887224932135},
+ // Population kurtosis
+ "Kurtosis": {0.14431032604193028, -0.8979764294956452},
+ "Variance": {65.0314538961039, 6.59910463333333},
+ // Population skewness
+ "Skewness": {-0.6233147473136348, -0.2757248239748126},
+ "NumValues": {22, 21},
+ "Min": {10.68, 13.691},
+ "Max": {41.08, 22.679},
+ }
+)
+
+func TestStats(t *testing.T) {
+ for i, set := range datasets {
+ s := &Stats{}
+ for _, n := range set {
+ s.Push(n)
+ }
+ for method, values := range expectedMethodResults {
+ t.Run(fmt.Sprintf("%s for set %d", method, i), func(t *testing.T) {
+ m := reflect.ValueOf(s).MethodByName(method).Call([]reflect.Value{})
+ // Round to three decimal places
+ got := math.Round(m[0].Float()*1000) / 1000
+ expected := math.Round(values[i]*1000) / 1000
+ if got != expected {
+ t.Errorf("Method %s failure: \n"+
+ "\tOn set: %d\n"+
+ "\tExpected: %f\n"+
+ "\tGot: %f\n",
+ method, i, expected, got)
+ }
+ })
+ }
+ }
+
+}