Skip to content

Commit cbd2ea3

Browse files
authored
Extend RunningVariance with min and max (#142)
* * Comments
1 parent ceff7f2 commit cbd2ea3

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/Helper/RunningVariance.php

+41
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class RunningVariance
3939
*/
4040
private int $count = 0;
4141

42+
/** The smallest observed value */
43+
private float $min = NAN;
44+
45+
/** The largest observed value */
46+
private float $max = NAN;
47+
4248
/** First moment: the mean value. */
4349
private float $mean = 0.0;
4450

@@ -61,6 +67,19 @@ public function observe(float $value): float
6167
$this->mean += $delta / $this->count;
6268
$this->m2 += $delta * ($value - $this->mean);
6369

70+
if (1 === $this->count) {
71+
$this->min = $value;
72+
$this->max = $value;
73+
} else {
74+
if ($value < $this->min) {
75+
$this->min = $value;
76+
}
77+
78+
if ($value > $this->max) {
79+
$this->max = $value;
80+
}
81+
}
82+
6483
return $value;
6584
}
6685

@@ -72,6 +91,18 @@ public function getCount(): int
7291
return $this->count;
7392
}
7493

94+
/** The smallest observed value */
95+
public function getMin(): float
96+
{
97+
return $this->min;
98+
}
99+
100+
/** The largest observed value */
101+
public function getMax(): float
102+
{
103+
return $this->max;
104+
}
105+
75106
/**
76107
* Get the mean value.
77108
*/
@@ -129,6 +160,8 @@ private function merge(self $other): void
129160
$this->count = $other->count;
130161
$this->mean = $other->mean;
131162
$this->m2 = $other->m2;
163+
$this->min = $other->min;
164+
$this->max = $other->max;
132165

133166
return;
134167
}
@@ -139,5 +172,13 @@ private function merge(self $other): void
139172
$this->mean = ($this->count * $this->mean) / $count + ($other->count * $other->mean) / $count;
140173
$this->m2 = $this->m2 + $other->m2 + ($delta ** 2 * $this->count * $other->count / $count);
141174
$this->count = $count;
175+
176+
if ($other->min < $this->min) {
177+
$this->min = $other->min;
178+
}
179+
180+
if ($other->max > $this->max) {
181+
$this->max = $other->max;
182+
}
142183
}
143184
}

tests/Helper/RunningVarianceTest.php

+32
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public function testEmpty(): void
5151

5252
$this->assertSame(0, $variance->getCount());
5353
$this->assertNan($variance->getMean());
54+
$this->assertNan($variance->getMin());
55+
$this->assertNan($variance->getMax());
5456
$this->assertNan($variance->getVariance());
5557
$this->assertNan($variance->getStandardDeviation());
5658
}
@@ -72,10 +74,26 @@ public function testOne(): void
7274

7375
$this->assertSame(1, $variance->getCount());
7476
$this->assertSame(M_PI, $variance->getMean());
77+
$this->assertSame(M_PI, $variance->getMin());
78+
$this->assertSame(M_PI, $variance->getMax());
7579
$this->assertSame(0.0, $variance->getVariance());
7680
$this->assertSame(0.0, $variance->getStandardDeviation());
7781
}
7882

83+
public function testOneNegative(): void
84+
{
85+
$variance = new RunningVariance();
86+
$variance->observe(-1.01);
87+
88+
$this->assertSame(1, $variance->getCount());
89+
$this->assertSame(-1.01, $variance->getMean());
90+
$this->assertSame(-1.01, $variance->getMin());
91+
$this->assertSame(-1.01, $variance->getMax());
92+
$this->assertSame(0.0, $variance->getVariance());
93+
$this->assertSame(0.0, $variance->getStandardDeviation());
94+
}
95+
96+
7997
public function testTwo(): void
8098
{
8199
$variance = new RunningVariance();
@@ -84,6 +102,8 @@ public function testTwo(): void
84102

85103
$this->assertSame(2, $variance->getCount());
86104
$this->assertSame(M_PI, $variance->getMean());
105+
$this->assertSame(M_PI, $variance->getMin());
106+
$this->assertSame(M_PI, $variance->getMax());
87107
$this->assertSame(0.0, $variance->getVariance());
88108
$this->assertSame(0.0, $variance->getStandardDeviation());
89109
}
@@ -96,6 +116,8 @@ public function testNAN(): void
96116

97117
$this->assertSame(2, $variance->getCount());
98118
$this->assertNan($variance->getMean());
119+
$this->assertSame(M_PI, $variance->getMin());
120+
$this->assertSame(M_PI, $variance->getMax());
99121
$this->assertNan($variance->getVariance());
100122
$this->assertNan($variance->getStandardDeviation());
101123
}
@@ -111,6 +133,8 @@ public function testFive(): void
111133

112134
$this->assertSame(5, $variance->getCount());
113135
$this->assertSame(5.0, $variance->getMean());
136+
$this->assertSame(2.0, $variance->getMin());
137+
$this->assertSame(8.0, $variance->getMax());
114138
$this->assertEqualsWithDelta(5.0, $variance->getVariance(), 0.0001);
115139
$this->assertEqualsWithDelta(sqrt(5.0), $variance->getStandardDeviation(), 0.0001);
116140
}
@@ -128,6 +152,8 @@ public function testCopy(): void
128152

129153
$this->assertSame(5, $variance->getCount());
130154
$this->assertSame(5.0, $variance->getMean());
155+
$this->assertSame(2.0, $variance->getMin());
156+
$this->assertSame(8.0, $variance->getMax());
131157
$this->assertEqualsWithDelta(5.0, $variance->getVariance(), 0.0001);
132158
$this->assertEqualsWithDelta(sqrt(5.0), $variance->getStandardDeviation(), 0.0001);
133159
}
@@ -145,6 +171,8 @@ public function testFiveMerged(): void
145171

146172
$this->assertSame(5, $variance->getCount());
147173
$this->assertSame(5.0, $variance->getMean());
174+
$this->assertSame(2.0, $variance->getMin());
175+
$this->assertSame(8.0, $variance->getMax());
148176
$this->assertEqualsWithDelta(5.0, $variance->getVariance(), 0.0001);
149177
$this->assertEqualsWithDelta(sqrt(5.0), $variance->getStandardDeviation(), 0.0001);
150178
}
@@ -164,6 +192,8 @@ public function testFiveMergedTwice(): void
164192

165193
$this->assertSame(5, $variance->getCount());
166194
$this->assertSame(5.0, $variance->getMean());
195+
$this->assertSame(2.0, $variance->getMin());
196+
$this->assertSame(8.0, $variance->getMax());
167197
$this->assertEqualsWithDelta(5.0, $variance->getVariance(), 0.0001);
168198
$this->assertEqualsWithDelta(sqrt(5.0), $variance->getStandardDeviation(), 0.0001);
169199
}
@@ -185,6 +215,8 @@ public function testFiveMergedThrice(): void
185215

186216
$this->assertSame(5, $variance->getCount());
187217
$this->assertSame(5.0, $variance->getMean());
218+
$this->assertSame(2.0, $variance->getMin());
219+
$this->assertSame(8.0, $variance->getMax());
188220
$this->assertEqualsWithDelta(5.0, $variance->getVariance(), 0.0001);
189221
$this->assertEqualsWithDelta(sqrt(5.0), $variance->getStandardDeviation(), 0.0001);
190222
}

0 commit comments

Comments
 (0)