Every factorial approximates a power
johndcook.com
johndcook.com
This is super useful for combinatorial problems too, because gamma(N+1) = N!. Some examples where I've used it include:
- Erasure code durability math. The standard approximation has a N!/k! factor (see [1], equation 2.3), which gets out of hand numerically as N gets large. gamma(20) is 1.2e17, while lgamma(20) is only 39.3.
- Hash code collision math. The standard solution (see [2], for example) includes a factor of N!, which is an alarmingly big number when N is 2**128. In these cases, even the lgamma often doesn't fit into a 'double', and you need both logs and arbitrary precision to find exact solutions (better behaved approximations exist).
[1] "Notes on Reliability Models for Non-MDS Erasure Codes" https://dominoweb.draco.res.ibm.com/reports/rj10391.pdf [2] https://en.wikipedia.org/wiki/Birthday_problem
exp(lgamma(n+1) - lgamma(k+1)).
The form I use for the approximation is:
gamma(x) = factor(x) * lanczos_sum_expg_scaled(x)
where
factor(x) = ((x + lanczos_g - 0.5)/e)*(x - 0.5)
and lanczos_g is a constant.
When dealing with Gamma ratios, you can often cancel the factors nicely, giving a highly accurate approximation which doesn't overflow. It's curious I saw your comment when I did. I was just tinkering with the Lanczos approximation earlier today.
If you use Python, the Lanczos approximation is available in SciPy using
from scipy.special._ufuncs import _lanczos_sum_expg_scaled
and you can use lanczos_g = 6.024680040776729583740234375
[0] https://www.boost.org/doc/libs/1_82_0/libs/math/doc/html/mat...
factor(x) = ((x + lanczos_g - 0.5)/e)**(x - 0.5).
Take your desired probability, say one-in-a-million
prob = 0.999999
And calculate the bitspace. In this case, 12 base-62 digits space = 62 ** 12
Take the natural log of the probability, times -2, times the bitspace. The sqrt of that is approximately the number of items that can be shoved into the bitspace before there is a one-in-a-million chance of collision. int(math.sqrt((-2 * math.log(prob)) * space))
--> 80327683
With 80 million items, the odds of a collision are still 10*6 to 1 against.So, if b(n) is the base in b^n=n!, then b(n) is about (n/e). [I see this as the key observation of the article.]
Keeping in mind that (n/e)^n is a bit smaller than n!, a more accurate value for b(n) is a little higher than n/e.
So it makes sense that 25! ~= 10^25 because 25/e is a bit below 10, and the adjusted value for b(n) ought to be a little higher than 25/e; 10 will do in this case.
(And 270! ~= 100^270, etc.)
b = n/e + ln(2πn)/2e + (3(ln(2πn))^2 + 2)/(24en) + o(1/n)
which becomes a good approximation for large n: https://colab.research.google.com/drive/17cC8YUqKjEBLsNJkJ4I...An interesting question is whether you can show this without resorting to Bertrand's postulate.
(After thinking about it some more, perhaps not trivially.)
25! is 25 times bigger than 24! while 10^25 is 10 times bigger than 10^24?
It's simpler to remember that 24.5! ≈ 10^24.5 (accurate to within +/- 3%; see https://www.wolframalpha.com/input?i=solve+x%21+%3D+10%5Ex)
2 + 2 = 5 for large values of "2"The linked post is more informative: https://www.johndcook.com/blog/2023/06/22/mentally-approxima...
Going up to the next factorial bumps it up (approximately) another power of ten since you are multiplying by 2.5 and 10. In reality it’s around 1.5e25 which is also a reasonable approximation.
Over simplification: a number times 25 is closer to the number times 10 than it is to the number times 100.
better: (x!)^(1/x) ~ x/e - 1.8 * ln(ln(x))
https://www.wolframalpha.com/input?i=+%28x%21%29%5E%281%2Fx%...
> What’s interesting is that b is very nearly a linear function of n.
However, since the biggest term in the sum of 2n positive numbers is clearly within a factor 2n of the entire sum, the ratio of the logarithms is at least log(2^(2n) / 2n) / log(2^(2n)) = 1-log(2n)/(2n) which converges to one pretty quickly.
And, in fact, a tighter analysis would show that the error decreases faster than what I outlined.
is the same as
$(n!)^(1/n)$
which is obviously what the article is about.Why write it the complicated way? Are `exp` and `log` more usable than $^n$ in some context?
False. Probably the author meant to use "≈" twice.
And I'm still confused. What does "≈" mean, exactly? Is 2+2≈3^^3?
30! = 12.04449703813164.... ** 30
It's leading on to the next part: "What’s interesting is that b is very nearly a linear function of n. In hindsight it’s clear that this should be the case—it follows easily from Stirling’s approximation—but I didn’t anticipate this before I plotted it."The article also says, you can find a base b such that n! = b^n for any factorial. Guess what, you can do this for any number x and any n to find b such that x = b^n, whether x is a factorial or not: b is x ^ (1/n). Not sure what Stirling's approximation should have to do with this, and why = and ≈ are being used inconsistently in this post.
Ignoring my complaints of this particular post, this is a pretty great blog though, and I remember being helped by the linked older blog post article about log1p and expm1 before!
I've never actually worked with Stirling's approximation, but I guess if you have a certain set of context, this fact would be obvious?
Irrational Number: I'm a non-integer, Greg. Can you square root me?
Why?
> My colleagues and I have decades of consulting experience helping companies solve complex problems involving data privacy, math, statistics, and computing.
> Let’s talk. We look forward to exploring the opportunity to help your company too.
Getting more attention then clarifying the intent in the body is sometimes mischievous (read: every tabloid newspaper), but it nonetheless brings more good attention that it would have without the click bait. If that leads to more consulting work for the author, good for him.
(it kind of feels weird calling a high-number approximation “clickbait” but, in some circles…)
For every natural n, there exists a natural b, such that: n! ≈ b^n
I don't quite know the precise criteria for "≈" here, that's a bit beyond my understanding of the article...The fact is that `e * (n!)^(1/n)` is quite close to `n`.
But John didn't factor out the `e`, causing the confusion in this HN post's threads.
- If you only allow the base to be an integer, then it's inaccurate.
- If you allow the base to be a real number, then you're really just saying "every factorial is a positive number", which is a trivial fact if you know what a factorial is.
Either way it's a bad title IMO.
EDIT: whoever is downvoting me, the article title is objectively clickbait
The language is annoyingly misleading, and the seemingly random use of = and ≈ is frustrating.
Either my math or my english is failing me.
6.20 ≈ 10.00; 1.55 ≈ 1.00; 2.37 ≈ 2.65
That's like when my friend tortured her kid (and me) by asking how old I was, which was answered with "75". That is a very wide margin of error there.
It’s Stirling’s approximation, as the article mentions. The formula uses the ≈ character. The Wikipedia article gives bounds on the error—
Numerically, the point of the article is the fact that
n! \approx (0.826523 + n*0.373522)^n
For n in the range from 10 to 50, this is within 5% of the right answer.
But I really don't see that this is all that much simpler than Stirling's approximation and it is considerably less accurate and not asymptotically very good. Stirling's formula is within about 1% for all n>10 and within 0.1% for n>90.
Actually computing gamma(n) or lgamma(n) to high precision requires a bit more effort than this, but as an approximation, Stirling's formula is really pretty good.