Let me say up front that relying on the normal distribution as an accurate model of extreme events is **foolish** under most circumstances. The main reason to calculate the probability of, say, a 40 sigma event is to show how absurd it is to talk about 40 sigma events. See my previous post on six-sigma events for an explanation.

For this post I’ll be looking at two-tailed events, the probability that a normal random variable is either less than −*k*σ or greater than *k*σ. If you’re only interested in one of these two probabilities, divide by 2. Also, since the results are independent of σ, let’s assume σ = 1 for convenience.

The following Python code will print a table of *k*-sigma event probabilities.

from scipy.stats import norm for k in range(1, 40): print(k, 2*norm.cdf(-k))

This shows, for example, that a “25 sigma event,” something I’ve heard people talk about with a straight face, has a probability of 6 × 10^{−138}.

The code above reports that a 38 or 39 sigma event has probability 0, exactly 0. That’s because the actual value, while not zero, is so close to zero that floating point precision can’t tell the difference. This happens around 10^{−308}.

What if, despite all the signs warning *hic sunt dracones* you want to compute even smaller probabilities? Then for one thing you’ll need to switch over to log scale in order for the results to be representable as floating point numbers.

Exactly computing these extreme probabilities is challenging, but there are convenient upper and lower bounds on the probabilities that can be derived from Abramowitz and Stegun, equation 7.1.13 with a change of variables. See notes here.

We can use these bounds to compute upper and lower bounds on the base 10 logs of the tail probabilities.

from scipy import log, sqrt, pi def core(t, c): x = 2*sqrt(2/pi)/(t + sqrt(t**2 + c)) ln_p = -0.5*t**2 + log(x) return ln_p/log(10) def log10_upper(t): return core(t, 8/pi) def log10_lower(t): return core(t, 4)

This tells us that the log base 10 of the probability of a normal random variable being more than 38 standard deviations away from its mean is between −315.53968 and −315.53979. The upper and lower bounds agree to about seven significant figures, and the accuracy only improves as *k* gets larger. So for large arguments, we can use either the upper or lower bound as an accurate approximation.

The code above was used to compute this table of tail probabilities for *k* = 1 to 100 standard deviations.

There are somewhat simpler tail bounds which are easier to prove as well: https://statisticaloddsandends.wordpress.com/2018/02/18/bounding-the-normal-tail/