求圆周率的程序计算代码,是那种计算无限位数的,
大家都知道π=3。1415926……无穷多位, 历史上很多人都在计算这个数, 一直认为是一个非常复杂的问题。现在有了电脑, 这个问题就简单了。电脑可以利用级数计算出很多高精度的值, 有关级数的问题请参考《高等数学》,以下是比较有名的有关π的级数: 其中有些计算起来很复杂, 我们可以选用第三个, 比较简单, 并且收敛的非常快。 因为计算π值, 而这个公式是计算π/2的, 我们把它变形:π = 2 2/3 2/3*2/5 2/3*2/5*3/7 。。。 --------------------------------------------------------------...全部
大家都知道π=3。1415926……无穷多位, 历史上很多人都在计算这个数, 一直认为是一个非常复杂的问题。现在有了电脑, 这个问题就简单了。电脑可以利用级数计算出很多高精度的值, 有关级数的问题请参考《高等数学》,以下是比较有名的有关π的级数: 其中有些计算起来很复杂, 我们可以选用第三个, 比较简单, 并且收敛的非常快。
因为计算π值, 而这个公式是计算π/2的, 我们把它变形:π = 2 2/3 2/3*2/5 2/3*2/5*3/7 。。。 --------------------------------------------------------------------------------对于级数, 我们先做个简单测试, 暂时不要求精度:用 C Builder 新建一个工程, 在 Form 上放一个 Memo1 和 一个 Button1, 在 Button1 的 OnClick 事件写:void __fastcall TForm1::Button1Click(TObject *Sender){double x=2, z=2;int a=1, b=3;while(z>1e-15){ z = z*a/b; x = z; a ; b =2;}Memo1->Text = AnsiString()。
sprintf("Pi=%。13f", x);} 按Button1在Memo1显示出执行结果:Pi=3。1415926535898--------------------------------------------------------------------------------这个程序太简单了, 而且 double 的精度很低, 只能计算到小数点后 10 几位。
把上面的程序改造一下, 让它精确到小数点后面 1000 位再测试一下:在 Form 上再放一个按钮 Button2, 在这个按钮的 OnClick 事件写:void __fastcall TForm1::Button2Click(TObject *Sender){const ARRSIZE=1010, DISPCNT=1000; //定义数组大小,显示位数char x[ARRSIZE], z[ARRSIZE]; //x[0] x[1] 。
x[2] x[3] x[4] 。。。。 x[ARRSIZE-1]int a=1, b=3, c, d, Run=1, Cnt=0;memset(x,0,ARRSIZE);memset(z,0,ARRSIZE);x[1] = 2;z[1] = 2;while(Run && ( Cnt0; i--) { c = z*a d; z = c % 10; d = c / 10; } //z/=b; d = 0; for(int i=0; i0; i--) { c = x z; x = c; x[i-1] = c/10; Run |= z; } a ; b =2;}Memo1->Text = AnsiString()。
sprintf("计算了 %d 次
",Cnt);Memo1->Text = Memo1->Text AnsiString()。sprintf("Pi=%d%d。
", x[0],x[1]);for(int i=0; iText = Memo1->Text "
"; Memo1->Text = Memo1->Text (int)x[i 2];}} 按 Button2 执行结果:Pi=03。
1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989--------------------------------------------------------------------------------这下心理有底了, 是不是改变数组大小就可以计算更多位数呢?答案是肯定的。
如果把定义数组大小和显示位数改为:const ARRSIZE=10100, DISPCNT=10000; //定义数组大小,显示位数执行结果精度可达 10000 位:Pi=03。14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151。
。。 限于篇幅, 这里就省略了, 还是留给你自己来算吧!50201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678--------------------------------------------------------------------------------提高精度的原理:以上程序的原理是利用数组把计算结果保存起来, 其中数组每一项保存10进制数的一位,小数点定位在数组第1个数和第二个数之间, 即小数点前面2位整数, 其余都是小数位。
利用电脑模拟四则运算的笔算方法来实现高精度的数据计算,没想到最原始的方法竟然是精度最高的。---------------------------------------用汇编语言编制计算程序并不是强项,特别是在涉及到浮点计算时,但汇编的一个好处就是速度快,所以在整数计算时可以试一下。
本文的理论基础来自是电脑杂志1996年第10期,作者郭继展发表的一篇文章,作者提出一个公式: PI=16arctg(1/5)-4arctg(1/239)在展开成两个级数之和,然后整理得到: PI=16x(1/5-1/(5^3/3) 1/(5^5/5)-1/(5^7/7) 。
。。)-4x(1/239-1/(239^3/3) 1/(239^5/5)-1/(239^7/7) 。。。) =4x(4x5/25-239/57121)/1-4x(4x5/25^2-239/57121^2)/3 4x(4x5/25^3-239/57121^3)/5-。
。。 我对以上公式和推导一看就头疼,但根据它编出的程序却可以在4分钟内算出圆周率的小数点下8万位!(在P5/200上)想当年祖冲之算了一生才算到3。14159265,十九世纪英国人香克思用了一生才算到小数点下707位。
本程序的难点就是如何达到小数点下这么多位的精度,这个办法就是:在计算机中一个 WORD 可以表示0到65535,我们可以在内存定义一个字来表示五位数,如果要算到小数点下10000位,则定义2000个字来表示它,如计算239/57121时,可以用23900000/57121,得到小于五位的结果存到第一个字中,然后用余数乘以100000再除57121,得到小于五位的结果存到第二个字中,依此类推。
为了计算时不至于溢出,本程序动用一个双字来表示五位数,再用一个段64K来表示一个高精度数,共可以表示(65536/4)*5 共有小数点下 81920 位。一共用到三个段,第一个段存储(4*4*5/25^n),第二个段存储(4*239/57121^n),第三个段存储最后的结果即 PI。
收起