Fix error calculation for tests.
Change sample generation to rand.NormFloat64 to expose previous problem.
Bjoern Rabenstein
8 years ago
0 | 0 | package quantile |
1 | 1 | |
2 | 2 | import ( |
3 | "math" | |
4 | 3 | "math/rand" |
5 | 4 | "sort" |
6 | 5 | "testing" |
11 | 10 | a := make([]float64, 0, 1e5) |
12 | 11 | rand.Seed(42) |
13 | 12 | for i := 0; i < cap(a); i++ { |
14 | v := float64(rand.Int63()) | |
13 | v := rand.NormFloat64() | |
15 | 14 | s.Insert(v) |
16 | 15 | a = append(a, v) |
17 | 16 | } |
18 | 17 | t.Logf("len: %d", s.Count()) |
19 | 18 | sort.Float64s(a) |
20 | w := getPerc(a, 0.50) | |
21 | if g := s.Query(0.50); math.Abs(w-g)/w > 0.03 { | |
22 | t.Errorf("perc50: want %v, got %v", w, g) | |
23 | t.Logf("e: %f", math.Abs(w-g)/w) | |
19 | w, min, max := getPerc(a, 0.50) | |
20 | if g := s.Query(0.50); g < min || g > max { | |
21 | t.Errorf("perc50: want %v [%f,%f], got %v", w, min, max, g) | |
24 | 22 | } |
25 | w = getPerc(a, 0.90) | |
26 | if g := s.Query(0.90); math.Abs(w-g)/w > 0.03 { | |
27 | t.Errorf("perc90: want %v, got %v", w, g) | |
28 | t.Logf("e: %f", math.Abs(w-g)/w) | |
23 | w, min, max = getPerc(a, 0.90) | |
24 | if g := s.Query(0.90); g < min || g > max { | |
25 | t.Errorf("perc90: want %v [%f,%f], got %v", w, min, max, g) | |
29 | 26 | } |
30 | w = getPerc(a, 0.99) | |
31 | if g := s.Query(0.99); math.Abs(w-g)/w > 0.03 { | |
32 | t.Errorf("perc99: want %v, got %v", w, g) | |
33 | t.Logf("e: %f", math.Abs(w-g)/w) | |
27 | w, min, max = getPerc(a, 0.99) | |
28 | if g := s.Query(0.99); g < min || g > max { | |
29 | t.Errorf("perc99: want %v [%f,%f], got %v", w, min, max, g) | |
34 | 30 | } |
35 | 31 | } |
36 | 32 | |
50 | 46 | rand.Seed(42) |
51 | 47 | a := make([]float64, 0, 1e6) |
52 | 48 | for i := 0; i < cap(a); i++ { |
53 | v := float64(rand.Int63()) | |
49 | v := rand.NormFloat64() | |
54 | 50 | a = append(a, v) |
55 | 51 | ch <- v |
56 | 52 | } |
62 | 58 | |
63 | 59 | t.Logf("len: %d", s.Count()) |
64 | 60 | sort.Float64s(a) |
65 | w := getPerc(a, 0.50) | |
66 | if g := s.Query(0.50); math.Abs(w-g)/w > 0.03 { | |
67 | t.Errorf("perc50: want %v, got %v", w, g) | |
68 | t.Logf("e: %f", math.Abs(w-g)/w) | |
61 | w, min, max := getPerc(a, 0.50) | |
62 | if g := s.Query(0.50); g < min || g > max { | |
63 | t.Errorf("perc50: want %v [%f,%f], got %v", w, min, max, g) | |
69 | 64 | } |
70 | w = getPerc(a, 0.90) | |
71 | if g := s.Query(0.90); math.Abs(w-g)/w > 0.03 { | |
72 | t.Errorf("perc90: want %v, got %v", w, g) | |
73 | t.Logf("e: %f", math.Abs(w-g)/w) | |
65 | w, min, max = getPerc(a, 0.90) | |
66 | if g := s.Query(0.90); g < min || g > max { | |
67 | t.Errorf("perc90: want %v [%f,%f], got %v", w, min, max, g) | |
74 | 68 | } |
75 | w = getPerc(a, 0.99) | |
76 | if g := s.Query(0.99); math.Abs(w-g)/w > 0.03 { | |
77 | t.Errorf("perc99: want %v, got %v", w, g) | |
78 | t.Logf("e: %f", math.Abs(w-g)/w) | |
69 | w, min, max = getPerc(a, 0.99) | |
70 | if g := s.Query(0.99); g < min || g > max { | |
71 | t.Errorf("perc99: want %v [%f,%f], got %v", w, min, max, g) | |
79 | 72 | } |
80 | 73 | } |
81 | 74 | |
121 | 114 | } |
122 | 115 | } |
123 | 116 | |
124 | func getPerc(x []float64, p float64) float64 { | |
117 | func getPerc(x []float64, p float64) (want, min, max float64) { | |
125 | 118 | k := int(float64(len(x)) * p) |
126 | return x[k] | |
119 | lower := int(float64(len(x)) * (p - 0.04)) | |
120 | if lower < 0 { | |
121 | lower = 0 | |
122 | } | |
123 | upper := int(float64(len(x))*(p+0.04)) + 1 | |
124 | if upper >= len(x) { | |
125 | upper = len(x) - 1 | |
126 | } | |
127 | return x[k], x[lower], x[upper] | |
127 | 128 | } |