Skip to content

Commit 1e3a9c8

Browse files
committed
Adding sum, min and max to StreamingStat
1 parent 943acc3 commit 1e3a9c8

4 files changed

Lines changed: 111 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Changelog
22

33
## 1.3.0 - WIP
4-
- Adding `StreamingStat` class (experimental) for streaming/online computation of mean, variance, stdev, skewness, and kurtosis with O(1) memory
4+
- Adding `StreamingStat` class (experimental) for streaming/online computation of mean, variance, stdev, skewness, kurtosis, sum, min, and max with O(1) memory
55

66
## 1.2.5 - 2026-02-22
77
- Adding `kurtosis()` method for excess kurtosis

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,9 @@ $s = new StreamingStat();
980980
$s->add(1)->add(2)->add(3)->add(4)->add(5);
981981

982982
$s->count(); // 5
983+
$s->sum(); // 15.0
984+
$s->min(); // 1.0
985+
$s->max(); // 5.0
983986
$s->mean(); // 3.0
984987
$s->variance(); // 2.5
985988
$s->stdev(); // 1.5811...
@@ -990,6 +993,9 @@ $s->kurtosis(); // -1.2
990993
| Method | Description | Min n |
991994
|---|---|---|
992995
| `count()` | Number of values added | 0 |
996+
| `sum()` | Sum of all values | 1 |
997+
| `min()` | Minimum value | 1 |
998+
| `max()` | Maximum value | 1 |
993999
| `mean(?int $round = null)` | Arithmetic mean | 1 |
9941000
| `variance(?int $round = null)` | Sample variance | 2 |
9951001
| `pvariance(?int $round = null)` | Population variance | 1 |

src/StreamingStat.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,25 @@ class StreamingStat
2424

2525
private float $m4 = 0.0;
2626

27+
private float $sum = 0.0;
28+
29+
private float $min = PHP_FLOAT_MAX;
30+
31+
private float $max = -PHP_FLOAT_MAX;
32+
2733
/**
2834
* Add a value and update all accumulators using the online algorithm.
2935
*/
3036
public function add(int|float $value): self
3137
{
38+
$this->sum += $value;
39+
if ($value < $this->min) {
40+
$this->min = (float) $value;
41+
}
42+
if ($value > $this->max) {
43+
$this->max = (float) $value;
44+
}
45+
3246
$n1 = $this->n;
3347
$this->n++;
3448
$n = $this->n;
@@ -57,6 +71,42 @@ public function count(): int
5771
return $this->n;
5872
}
5973

74+
/**
75+
* Return the sum of all values added.
76+
*/
77+
public function sum(): float
78+
{
79+
if ($this->n < 1) {
80+
throw new InvalidDataInputException("The data must not be empty.");
81+
}
82+
83+
return $this->sum;
84+
}
85+
86+
/**
87+
* Return the minimum value added.
88+
*/
89+
public function min(): float
90+
{
91+
if ($this->n < 1) {
92+
throw new InvalidDataInputException("The data must not be empty.");
93+
}
94+
95+
return $this->min;
96+
}
97+
98+
/**
99+
* Return the maximum value added.
100+
*/
101+
public function max(): float
102+
{
103+
if ($this->n < 1) {
104+
throw new InvalidDataInputException("The data must not be empty.");
105+
}
106+
107+
return $this->max;
108+
}
109+
60110
/**
61111
* Return the arithmetic mean.
62112
*/

tests/StreamingStatTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,58 @@ public function test_empty_pvariance_throws(): void
224224
$this->expectException(InvalidDataInputException::class);
225225
(new StreamingStat())->pvariance();
226226
}
227+
228+
public function test_sum(): void
229+
{
230+
$data = [1.5, 2.5, 3.0, 4.0, 5.5];
231+
$s = $this->fromArray($data);
232+
$this->assertEqualsWithDelta(array_sum($data), $s->sum(), self::TOLERANCE);
233+
}
234+
235+
public function test_empty_sum_throws(): void
236+
{
237+
$this->expectException(InvalidDataInputException::class);
238+
(new StreamingStat())->sum();
239+
}
240+
241+
public function test_min(): void
242+
{
243+
$data = [3, -1, 4, 1, 5, -9, 2, 6];
244+
$s = $this->fromArray($data);
245+
$this->assertEqualsWithDelta(-9.0, $s->min(), self::TOLERANCE);
246+
}
247+
248+
public function test_empty_min_throws(): void
249+
{
250+
$this->expectException(InvalidDataInputException::class);
251+
(new StreamingStat())->min();
252+
}
253+
254+
public function test_max(): void
255+
{
256+
$data = [3, -1, 4, 1, 5, -9, 2, 6];
257+
$s = $this->fromArray($data);
258+
$this->assertEqualsWithDelta(6.0, $s->max(), self::TOLERANCE);
259+
}
260+
261+
public function test_empty_max_throws(): void
262+
{
263+
$this->expectException(InvalidDataInputException::class);
264+
(new StreamingStat())->max();
265+
}
266+
267+
public function test_min_max_single_element(): void
268+
{
269+
$s = (new StreamingStat())->add(42);
270+
$this->assertEqualsWithDelta(42.0, $s->min(), self::TOLERANCE);
271+
$this->assertEqualsWithDelta(42.0, $s->max(), self::TOLERANCE);
272+
}
273+
274+
public function test_min_max_negative_values(): void
275+
{
276+
$data = [-10.5, -3.2, -7.8];
277+
$s = $this->fromArray($data);
278+
$this->assertEqualsWithDelta(-10.5, $s->min(), self::TOLERANCE);
279+
$this->assertEqualsWithDelta(-3.2, $s->max(), self::TOLERANCE);
280+
}
227281
}

0 commit comments

Comments
 (0)