diff options
| author | Mitchell Riedstra <mitch@riedstra.dev> | 2021-01-23 13:44:24 -0500 |
|---|---|---|
| committer | Mitchell Riedstra <mitch@riedstra.dev> | 2021-01-23 13:44:24 -0500 |
| commit | 8702a4095f0d86949b69d379f587f4037d6516fd (patch) | |
| tree | 005d5c2ade491ee2464d67dce92e3341854c3e06 | |
| parent | a2245a9a1653dc25e899ea8b090d2c6be48b00a3 (diff) | |
| download | stats-8702a4095f0d86949b69d379f587f4037d6516fd.tar.gz stats-8702a4095f0d86949b69d379f587f4037d6516fd.tar.xz | |
Add working tests. Fix issue with min/max.
| -rw-r--r-- | print.go | 2 | ||||
| -rw-r--r-- | stats.go | 19 | ||||
| -rw-r--r-- | stats_test.go | 62 |
3 files changed, 76 insertions, 7 deletions
@@ -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 @@ -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) + } + }) + } + } + +} |
