当未知长度的单位 1 和已完成长度的单位 1 之间的比例不是 1:1 而是其它的数值的时候,不难看出,这时候的圆周率就变成了“椭圆周率”。你可能要说,这不是椭圆积分吗?对了,这就是椭圆积分。但是我们不要考虑什么椭圆积分,也就是“术”,而是从“术”去探寻后面的本质,也就是“道”。比如椭圆的周长为啥没有初等形式?
不难理解, 是写不出初等形式的。这里的初等形式就是不用什么无穷展开式的形式,就能表达的(反三角函数不算初等形式),无穷展开式也可以被认为是积分的计算式,这就必然引入高等数学的微积分。对于自然对数底 e ,我们可以写一个简单的极限形式,但是上面分析可以看出圆周率 无法写成简单的极限形式。可是为什么呢?为什么 必须写成无穷展开形式?这里有一个关键的原因,就是它不是等比数列,而是“类等比数列”,也就是说,它并不基本。正如分析中看到的,它的每一个细节都是重要的,不可忽略的,不可压缩的,数值上不重复的。这些细节必须都如其所是的展现和应用,才能得到预期的结果。比如我们可以考虑一下,“世界的深度”问题。
我们知道,已知的物理世界中的最小长度单位是普朗克长度,其数值约为
小于这个长度的长度数值是没有意义的。我们想知道的是,圆周率的精度要达到多少才能满足精确的描述到这个长度而不出错。
根据奈奎斯特定理,只要精度可以达到这个长度的一半,就不会出错。也就是,
比如现在有 1 米的长度,它含有多少个“半普朗克长度"?
因为圆周率对应的本质是无穷分辨率二分法,那么我们要做的就是给出 1 米要二分多少次才能实现 的 倍,也就是,
也就是把 1 米二分 117 次就能到达 的尺度。而要满足从 1 到 的所有分辨率,则
中的,
也就是算上第一个 1 一共 118 项。用 WallisProductForPi 程序计算,
=3.1415926535897932384626433832795028837117542690193978304300692906910722764246484779868671982472968461145914502030480042149194000360931827741286277693646703759569539131095642059921717455856699298162590746974495626887754567548573247048
Iterates = 118, Digits = 233, Duration = 00:00:00.0069917
算上最开始的 3 ,一共 234 个十进制位。也就是说,一个半径 1 米的圆盘,若要精细的计算其周长和面积,用上面给出的 234 个十进制位的圆周率,就可以精确到普朗克长度的一半,也就是精确到物理世界的最大分辨率。据查,已知人类可观测的最大长度为
那么最大和最小尺度之间的比率为
将 204 带入 WallisProductForPi ,得到,
=3.141592653589793238462643383279502884197169399375105820974944587513348308572560229674272821127637787898485165318568647570710675728761324048835622098710634183609348219866616974523465089020053331090156730307545037331007369768879293569304740977253050027216660075271319160441643206305077047929875585522104215303330035764504506317993204269519538392068950265924625668981683394944286112129077815440181088261161977466484203656470088070977234403307910403981
Iterates = 204, Digits = 448, Duration = 00:00:00.0088822
算上最开始的 3 ,一共 449 个十进制位。也就是说,从可观宇宙的最大长度到微观世界的最小长度,用 449 位十进制的圆周率就足够精确了。
using System.Diagnostics;
using System.Numerics;namespace WallisFormulaForPi;public class Program
{//计算圆周率的沃里斯乘积算法//分子和分母分别计算//最后彼此相除//可以得到极高精度的计算结果//Pi/2 = Sum(n!/(2n+1)!!,n>=0)//Pi/2 = 0!/1! + 1!/3! + 2!/5!+...static BigInteger WallisProductForPi(BigInteger n){var upper = n;var lower = (n << 1) + 1;upper += lower;for (--n; n >= 1; --n){upper *= n;upper += (lower *= ((n << 1) + 1));}upper *= BigInteger.Pow(10, (int)Math.Ceiling(BigInteger.Log10(lower)));return (upper << 1) / lower;}//单阶乘static long Factorial1(long n) => n >= 1 ? n * Factorial1(n - 1) : 1;//双阶乘static long Factorial2(long n) => n >= 1 ? n * Factorial2(n - 2) : 1;/// </summary>/// <param name="args"></param>static void Main(string[] args){BigInteger n = 204;var stopwatch = new Stopwatch();stopwatch.Start();var pi = WallisProductForPi(n);stopwatch.Stop();Console.WriteLine($"pi={pi}");Console.WriteLine($"Iterates = {n}, Digits = {(int)Math.Ceiling(BigInteger.Log10(pi))}, Duration = {stopwatch.Elapsed}");}
}