程序计算精确圆周率Pai的方法
来源:互联网 发布:淘宝号实名认证几个 编辑:程序博客网 时间:2024/05/20 17:26
一些参考资料:
http://www.guokr.com/blog/444081/
大家都知道π=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 && (++Cnt<200000000)) { //z*=a; d = 0; for(int i=ARRSIZE-1; i>0; i--) { c = z[i]*a + d; z[i] = c % 10; d = c / 10; } //z/=b; d = 0; for(int i=0; i<ARRSIZE; i++) { c = z[i]+d*10; z[i] = c / b; d = c % b; } //x+=z; Run = 0; for(int i=ARRSIZE-1; i>0; i--) { c = x[i] + z[i]; x[i] = c%10; x[i-1] += c/10; Run |= z[i]; } a++; b+=2; } Memo1->Text = AnsiString().sprintf("计算了 %d 次\r\n",Cnt); Memo1->Text = Memo1->Text + AnsiString().sprintf("Pi=%d%d.\r\n", x[0],x[1]); for(int i=0; i<DISPCNT; i++) { if(i && ((i%100)==0)) Memo1->Text = Memo1->Text + "\r\n"; Memo1->Text = Memo1->Text + (int)x[i+2]; }}
按 Button2 执行结果:
Pi=03.
1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196
4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273
7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094
3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912
9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132
0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235
4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859
5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303
5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
这下心理有底了, 是不是改变数组大小就可以计算更多位数呢?答案是肯定的。
如果把定义数组大小和显示位数改为:
const ARRSIZE=10100, DISPCNT=10000; //定义数组大小,显示位数
执行结果精度可达 10000 位:
Pi=03.
1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196
4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273
7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094
3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912
9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132
0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235
4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859
5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303
5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151
… 限于篇幅, 这里就省略了, 还是留给你自己来算吧!
5020141020672358502007245225632651341055924019027421624843914035998953539459094407046912091409387001
2645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678
提高精度的原理:
以上程序的原理是利用数组把计算结果保存起来, 其中数组每一项保存10进制数的一位,
小数点定位在数组第1个数和第二个数之间, 即小数点前面2位整数, 其余都是小数位。
利用电脑模拟四则运算的笔算方法来实现高精度的数据计算,没想到最原始的方法竟然是精度最高的。
/某年Obfuscated C Contest佳作选录: 800位精度圆周率/
#include < stdio.h>long a=10000, b, c=2800, d, e, f[2801], g; main(){for(;b-c;)f[b++]=a/5; for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a) for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}
////////////将以上精简的程序详细include_stdioint
a=10000,b,c=2800,d,e,f[2801],g;main() {int i;e=0;for(i=0;i<c;i++) f[i]=a/5;while(c!=0) { d=0; g=c*2; b=c; while(1) { d=d+f[b]*a; g--; f[b]=d%g; d=d/g; g--; b--; if(b==0) break; d=d*b; } c=c-14; printf("%.4d",e+d/a); e=d%a; }}
//根据这个思想,我们可以轻易的算出 自然对数底 e=2.71828….的任意位数
//////e=1+1/1!+1/2!+1/3!+…………+1/n!=1+1/2*(1+1/3*(1+……*(1+1/n))..)));
int main(int argc,char* argv[]){#define TIMES 100 ///输出e有效位数int n,c,e,d,i,f[TIMES+1];i=TIMES;while(i--){ f[i]=10;}printf("e=2.");i=0;e=0;while(i++<TIMES){d=0;c=TIMES;for(n=c;n>0;n--){ d=d+f[n]*10; f[n]=d%n;///////余数 d=d/(n);//////整数} printf("%d",(e+d/10)%10); e=d%10;}getchar();return 0;}
- 程序计算精确圆周率Pai的方法
- 计算圆周率pai的公式:pai = 4*(1-1/3+1/5-1/7 ....)
- 圆周率pai
- 计算圆周率的C程序
- 用蒙特卡罗方法计算圆周率的近似值,java程序
- VB计算圆周率的方法
- 圆周率的精确解
- Jason Chen的计算圆周率的程序
- 计算圆周率的C++程序(30000位)
- 计算圆周率的最短C程序
- matlab计算圆周率的一种方法
- 圆周率的计算
- 圆周率的计算公式
- 运行Spark提供的计算圆周率的示例程序
- Java实现计算圆周率π的两种方法
- 编程时圆周率的精确取值
- 精确计算程序运行的时间
- 圆周率π的计算历程
- Java 自定义链表MiniList
- Deep Learning(深度学习)学习笔记整理系列之(一)
- LINUX内核内存管理kmalloc,vmalloc
- 工作常用的android adb shell命令 (mac环境)
- lua中操作符的优先级
- 程序计算精确圆周率Pai的方法
- 软件发布版本区别介绍
- FFMPEG-初探认识-YUV转RGB用例
- C语言中最常用标准库函数
- MySQL上线后根据status状态进行适当优化
- 关于斯诺登暴料部分卡商SIM卡密钥被窃取的几点想法
- react native 环境配置
- Swift3.0 功能一(持续更新)
- Android GridView实现多种不同布局样式显示数据