Scientific programming in Modula-9 — first steps

↖ contents

6 — Simple math and statistics

Stats is the library this project uses for its own science, and its numbers come with a pedigree: every procedure is gated against numpy and scipy — the p-values digit for digit — with the expected values checked into the repository, because a gate that regenerates what it compares against cannot fail. When the tutorial prints a p-value below, that number has an oracle behind it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
C6Stats.m9

expected output:

mean y    3.8000
std y     1.2212
median y  3.9500
p90 y     5.1500
slope     0.4952
intercept 2.0667
r         0.9933
p         0.00000074
Welch t   -5.5549
p         0.000242

What the library gives you, in the order a working analysis meets them: moments (Mean, Std, and the population forms), order statistics (Median, Percentile — numpy's linear interpolation rule, so your quartiles match your colleague's notebook), a normal fit, least-squares regression with scipy.linregress's five numbers, and both t-tests (TTest2 is Welch's — unequal variances assumed, which is the safe default for real measurements). The p-values are real two-sided probabilities computed through the incomplete beta function, not lookup-table approximations.

For reproducible synthetic data, Stats.Seed gives a deterministic Stream with uniform, integer, normal, exponential and log-normal draws — bit-for-bit reproducible, seed in, same sequence out, on every machine.

The NaN policy, and why it is a policy

Chapter 5 turned a declared gap into NaN. What happens when a NaN reaches a statistic?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
C6Nan.m9

expected output:

Stats.Mean refused the NaN (ValueRange)

It raises. The alternatives are both answers someone regrets: a NaN mean (correct IEEE, useless science) or the silently "helpful" skip, which changes n without telling you and turns "a third of my sample is missing" into a confident narrow confidence interval. Skipping is often what you want — chapter 5's filter loop is exactly that — but it must be the CALLER's visible decision, with the count in the caller's hands. A library that decides for you has decided your science.

One more time: a checked build runs within a few percent of the same code with every check stripped. A language does not have to choose between honest and fast.

← Previous: reading and writing data · Next: timeseries →