回 帖 发 新 帖 刷新版面

主题:[原创]写了个Machin公式算pi的程序,速度不快,算到小数点后面1万位

公式是

pi=16arctg(1/5)-4arctg(1/239)

int main(int argc, char* argv[])
{
    int const N=7200;
    int const M=10000;
    int const B=10000;
    int const L=4;
    // Machin公式 计算pi到一万位
    int s[M/L];
    int r1[N]={0},r2[N]={0},d1[N]={0},d2;
    int r3[N]={0},r4[N]={0},d3[N]={0},d4;
    int i,k,t,p=0,mp=M/L/20;

    r1[0]=1;
    r1[1]=3;
    r3[0]=4;

    printf("正在计算,请等待\n____________________\n");
    
    for(k=0;k<M/L;++k)
    {
        t=r1[0]*B;
        d1[0]=t/0x5;
        r1[0]=t%0x5;
        //
        t=r3[0]*B;
        d3[0]=t/0xEF;
        r3[0]=t%0xEF;
        s[k]=d1[0]-d3[0];
        int tag=0;
        for(i=1;i<N;++i)
        {
            t=r1[i]*B+d1[i-1];
            d1[i]=t/0x19;
            r1[i]=t%0x19;
            t=r2[i]*B+d1[i];
            d2=t/(2*i+1);
            r2[i]=t%(2*i+1);
            //
            t=r3[i]*B+d3[i-1];
            d3[i]=t/0xDF21;
            r3[i]=t%0xDF21;
            t=r4[i]*B+d3[i];
            d4=t/(2*i+1);
            r4[i]=t%(2*i+1);
            if(tag)
            {
                s[k]+=(d2-d4);
                tag=0;
            }
            else
            {
                s[k]+=(d4-d2);
                tag=1;
            }
        }
        if(p==mp)
        {
            printf(">");
            p=0;
        }
        else
            p++;
    }
    for(i=M/L-1;i>=0;i--)
    {
        while(s[i]>=B)
        {
            s[i-1]++;
            s[i]-=B;
        }
        while(s[i]<0)
        {
            s[i-1]--;
            s[i]+=B;
        }
    }
    printf("\npi=3.\n");
    for(i=0;i<M/L;++i)
        printf("%04d",s[i]);
    return 0;
}

复杂度是O(M*N),N是计算的项数,M是要精确到的位数,它们的关系要解个不等式。在Release下编译速度快一点,可能的优化是/和%运算的重复。

结果就自己试试,不帖出来了,经检查,发现最后两位不准确,公式本身决定的,前面都抽样检查过,应该没问题。

回复列表 (共32个回复)

沙发

唉,数学不好,看着晕晕的~

板凳

真厉害。。。>_<

3 楼

[quote]唉,数学不好,看着晕晕的~[/quote]

我自己都觉得这样的代码没办法弄得很容易懂,命名啊,注释啊,都显得苍白。也不是我故意写成这样,没办法,那个rx[]是余数,dx[]是商,依据还是那个公式,再加上级数展开。

4 楼

//油箱发现有一个。贴上比较一下
#include<iostream.h>
void main()
{
 const int ARRSIZE=10010,DISPCNT=10002;
 static char x[ARRSIZE],z[ARRSIZE];
 int i,a(1),b(3),c,d,Run(1),Cnt(0);
 x[1]=2;z[1]=2;
 while(Run&&(++Cnt<20000000))
 {
   //z*=a;
   d=0;
   for(i=ARRSIZE-1;i>0;i--)
   {
      c=z[i]*a+d;
      z[i]=c%10;
      d=c/10;
    }
    //z/=b;
    d=0;
    for(i=0;i<ARRSIZE;i++)
    {
       c=z[i]+d*10;
       z[i]=c/d;
       d=c%b;
    }
    //x+=z;
    Run=0;
    for(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;
  }
  cout<<"计算了次数为:"<<Cnt<<endl;
  d=0;
  for(i=2;i<DISPCNT;i++)
  {
     cout<<(int)x[i];
     d++;
     if((d%50)==0){cout<<endl;continue;}
     if((d%10)==0)cout<<' ';
   }
}

5 楼

看到过弄这个程序的说明,是另外一个公式,我不知道它的余项,所以没这么做。Machin公式应该是较快算法里最简单的一个,如果要更快的速度,一个高效的高精运算库是少不了的。

6 楼

刚写的,有公式的实现方法。

[url=http://blog.programfan.com/article.asp?id=24388]简单方法算pi和e,计算到小数点后面一万位
http://blog.programfan.com/article.asp?id=24388[/url]

7 楼

不错

8 楼

???怎么把arctan()变成级数呢?

9 楼

用泰勒级数展开

10 楼

4楼的程序,我怎么算了N久,然后出错了啊~~

我来回复

您尚未登录,请登录后再回复。点此登录或注册