2.4.2 利用割圆术求解圆周率
通过加减乘除的运算迭代求得某数的N次方根,这是意义非凡的数学成就,因为N次方程式据此可以计算出明确的方根数值,从而一举奠定了代数学的坚实基础。同时,结合“勾三股四弦五”的勾股定理,能够使用开平方运算求得直角三角形的斜边长。假设直角三角形的两条直角边分别为a和b,斜边为c,则有方程式a2+b2=c2 ,由此得到。已知a和b的长度,便能根据牛顿迭代法计算斜边的长度。不要小看勾股定理及其算法,利用它不但能开展三角函数运算,还能进一步求出圆周率π的数值。
众所周知,圆周率π是一个无限不循环小数,数学课本上给出的π近似值有3.14和3.1416两个,它跟勾股定理有什么关系呢?此事说来话长,早在上古时期的中国,人们就认为圆的周长与直径存在比例关系,当时成书的《周髀算经》中明确记载“圆径一而周三”,即圆的周长是直径的三倍(π=3)。后来于汉朝成书的《九章算术》沿用了《周髀算经》里“径一周三”的说法,当然这个估算的圆周率很不精确,三国时期的刘徽就发现“径一周三”只适用于圆的内接正六边形,具体情况如图2-4所示。
显然正六边形的每条边长外围还有一段弯曲的圆弧,六段圆弧构成了整个圆圈的周长,由于每段圆弧都比拉直的各边要长,因此圆周必然大于正六边形的周长,也就是说圆周率应当比数字3大一些。为了计算出精确的圆周率,刘徽在《九章算术注》中提出了著名的“割圆术”,从圆的内接正六边形开始,依次往外去割正十二边形、正二十四边形等,随着正N边形的边数增加,正N边形的周长越来越接近圆的周长。正所谓“割之弥细,所失弥少,割之又割,以至于不可割,则与圆周合体而无所失矣。”为了更直观地理解割圆术的精妙,来看图2-5所示的圆圈及其内接正六边形、内接正十二边形的形状组合。
图2-4 圆及其内接正六边形的周长
图2-5 圆的内接正六边形与内接正十二边形
由图2-5可见,内接正十二边形的周长更加接近圆周,从而表明割圆术的理论是正确的。不过内接正十二边形的边长该如何计算呢?这个问题必须解决,因为只有求得正N边形的边长,才能通过式子“正N边形的边长*边数/直径”计算出圆周率的近似值。由于内接正六边形的边长刚好等于圆的半径,因此不妨借助于正六边形计算正十二边形的边长。假定圆心为O点,内接正六边形的某条边为AB,且线段AB的两个端点都位于圆圈之上。接着在O点做AB的垂线,且垂线与圆圈相交于C点,与AB相交于D点,此时各点的分布情况如图2-6所示。
图2-6 圆的内接正十二边形的边长计算
然后分别连接AC两点与BC两点,可见线段AC和BC构成了内接正十二边形的两条边长,于是正十二边形的边长解法就变成了计算AC或BC的长度。假设圆的半径长度为r,则线段OA、OB、AB的长度均为r,同时因为垂线OD将三角形OAB二等分,所以线段AD与BD各为AB的一半长即。在直角三角形ODB中,根据勾股定理可知OB2=BD2+OD2,求得,进一步求得线段CD的长度:。注意到CDB三点依旧构成直角三角形,那么由勾股定理可得BC2=BD2+CD2,于是得到线段BC的长度:。倘若r值为1,求得内接正十二边形的边长,此时正十二边形的周长≈0.5176×12=≈6.212,将这个周长除以圆的直径长度2,可得正十二边形对应的圆周率π=6.212/2=3.106。显而易见,内接正十二边形的3.106要优于正六边形的3,要是继续割到内接正二十四边形,正二十四边形对应的圆周率又会比正十二边形更逼近真实的π值。
上述求解内接正十二边形边长的办法同样适用于正二十四边形、正四十八边形等,中心思想是先二等分每条边对应的等腰三角形,再连续运用勾股定理依次求得直角三角形的各边长,进而计算出内接正N边形的边长数值。如此每迭代一次运算,正N边形的边数就翻倍,反复迭代多次之后,内接正N边形就越来越趋向于圆圈,相应的圆周率数值也越来越精确。
当年刘徽从圆的内接正六边形开始,一直割到内接正192边形,并求得圆周率的近似值为3.14。但他拿官方的度量衡标准容器一验证,发现3.14还是偏小,于是继续往上一路割到圆的内接正3072边形,终于求出此时的圆周率值为3.1416。为了计算准确的圆周率数值,古今中外的众多数学家穷尽智慧,纷纷各显神通谋划圆周,知名的数学家除了刘徽外,还包括东汉数学家张衡、南北朝数学家祖冲之以及古希腊数学家阿基米德、印度数学家阿耶波多、波斯数学家花拉子米、意大利数学家斐波那契、阿拉伯数学家卡西、德国数学家鲁道夫、英国数学家牛顿和梅钦等,真可谓“圆周率如此多娇,引无数天才竞折腰”。他们各自推导的圆周率精度见表2-2。
表2-2 古代数学家计算的圆周率纪录
这些数学家中的佼佼者便是祖冲之,他在刘徽开创的割圆术的基础上,首次将圆周率推导至小数点后7位,即π值位于3.1415926和3.1415927之间,并且该纪录保持了近千年才被打破。为了便于日常运算,祖冲之还给出了圆周率的两个分数形式,其中22/7精确到小数点后两位,被称作“约率”;另一个355/113精确到小数点后7位,被称作“密率”,用于日常生活中的圆周、圆面积、球体积等运算已绰绰有余。
如今来到计算机时代,初学者只要利用割圆术的算法,结合编程语言的四则运算与数学函数,即可不费吹灰之力轻松求得较精确的圆周率值。仍从圆的内接正六边形开始,依次切割正十二边形、正二十四边形直至正三千零七十二边形,每次切割都根据勾股定理计算出直角三角形的各边长,且每次迭代过程编写的算法代码一模一样,后续迭代只需将首次的迭代代码复制粘贴一遍就行,具体的实现示例代码如下(完整代码见本章源码的src\com\arithmetic\Yuanzhoulv.java):
// 假设圆的半径r=1,则直径d=2,内接正六边形的边长=1 int r=1; // 半径 long edgeNumber=6L; // 从正六边形开始内接圆 double edgeLength=r; // 内接正n边形的边长(初始值为正六边形的边长) double π=edgeLength * edgeNumber / (2*r); // 圆周率 System.out.println("正n边形的边数="+edgeNumber+",圆周率="+π); double gou; // 直角三角形中长度最短的边,称作“勾” double gu; // 直角三角形中长度居中的边,称作“股” // 以下计算内接圆的正十二边形 edgeNumber=edgeNumber*2; // 正n边形的边数乘2 gou=edgeLength/2.0; // 计算勾 gu=r - Math.sqrt(Math.pow(r,2) - Math.pow(gou,2)); // 计算股 // 通过勾股定理求斜边长(勾三股四弦五),斜边长也是新正n边形的边长 edgeLength=Math.sqrt(Math.pow(gou,2) + Math.pow(gu,2)); // 正n边形的周长除以直径,即可得到近似的圆周率数值 π=edgeLength * edgeNumber / (2*r); System.out.println("正n边形的边数="+edgeNumber+",圆周率="+π); // 以下计算内接圆的正二十四边形 edgeNumber=edgeNumber*2; // 正n边形的边数乘2 gou=edgeLength/2.0; // 计算勾 gu=r - Math.sqrt(Math.pow(r,2) - Math.pow(gou,2)); // 计算股 // 通过勾股定理求斜边长(勾三股四弦五),斜边长也是新正n边形的边长 edgeLength=Math.sqrt(Math.pow(gou,2) + Math.pow(gu,2)); // 正n边形的周长除以直径,即可得到近似的圆周率数值 π=edgeLength * edgeNumber / (2*r); System.out.println("正n边形的边数="+edgeNumber+",圆周率="+π); // 此处省略正四十八边形、正九十六边形直到正三千零七十二边形的代码
运行以上的圆周率求解代码,观察到的输出日志如下:
正n边形的边数=6,圆周率=3.0 正n边形的边数=12,圆周率=3.105828541230249 正n边形的边数=24,圆周率=3.1326286132812378 正n边形的边数=48,圆周率=3.1393502030468667 正n边形的边数=96,圆周率=3.14103195089051 正n边形的边数=192,圆周率=3.1414524722854624 正n边形的边数=384,圆周率=3.141557607911858 正n边形的边数=768,圆周率=3.1415838921483186 正n边形的边数=1536,圆周率=3.1415904632280505 正n边形的边数=3072,圆周率=3.1415921059992717
可见随着内接正N边形的边数增加,求得的圆周率精度越来越高,当n=96的时候,圆周率精确到了3.14,当n=3072的时候,圆周率精确到了小数点后6位。从程序的运行结果可知,史书记载的刘徽割圆之事所言非虚。