易码技术论坛

 找回密码
 加入易码
搜索
查看: 178562|回复: 1

[转载]计算π值, 精确到小数点后 10000 位

[复制链接]
发表于 2005-1-15 11:50:00 | 显示全部楼层
那个没意思,要折磨CPU运行下面的
求费马素数:(VC下)
#include<iostream>
#include<iomanip.h>
using namespace std;
unsigned int a[1000000],n=0,c=0;
//prime array,match counter,array counter

void ScreenOut(unsigned long int prime)
{
unsigned int p;
for(p=c-1;p>0;p--) //from the front one
if(prime==(a*a+4))
{
//cout<<'\n';
cout<<setw(5)<<prime<<" = 2*2 + "<<setw(3)
<<a<<" * "<<setw(3)<<a<<endl;
n++;
}
}

void main()
{
unsigned long int i,count,quantity=10000000;
int judgement; //if the number is prime,assign 1
a[0]=2;
for(count=3;count<quantity;count+=2)
{//because odd,jump 2 steps once
judgement=1; //assign 1 every cycle
for(i=3;i<count/2;i++)
{
if(count%i==0)
{
judgement=0;
break;
}
}
if(judgement)
{
a[++c]=count; //if prime,assign to array
ScreenOut(count);
}
}
cout<<"\ntotal of match: "<<n<<'\n'<<endl;
}


 楼主| 发表于 2005-1-15 11:27:02 | 显示全部楼层 |阅读模式

首页程序源码VCL控件怀旧DOS软件发布网友留言 欢迎访问 C++ 爱好者网站计算圆周率 Pi (π)值, 精确到小数点后 10000 位
只需要 30 多句代码!
(浏览 20407 次)

Victor Chen, (C++ 爱好者)



大家都知道π=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*a + d;
      z = c % 10;
      d = c / 10;
    }
    //z/=b;
    d = 0;
    for(int i=0; i<ARRSIZE; i++)
    {
      c = z+d*10;
      z = c / b;
      d = c % b;
    }
    //x+=z;
    Run = 0;
    for(int i=ARRSIZE-1; i>0; i--)
    {
      c = x + z;
      x = c%10;
      x[i-1] += c/10;
      Run |= z;
    }
    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位整数, 其余都是小数位。

利用电脑模拟四则运算的笔算方法来实现高精度的数据计算,没想到最原始的方法竟然是精度最高的。


  

转载自C++ 爱好者网址: http://www.cppfans.com/

[此贴子已经被作者于2005-1-15 11:29:48编辑过]

您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-5-5 16:39 , Processed in 0.010073 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表