LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2662|回复: 11

有哪位兄弟知道super pi的算法?

[复制链接]
发表于 2005-5-15 08:44:48 | 显示全部楼层 |阅读模式
如题。我想编一个fortran程序,测试CPU浮点运算速度,这还是我们的作业呢。
发表于 2005-5-15 12:48:01 | 显示全部楼层
看看级数
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-15 13:09:59 | 显示全部楼层
是反三角函数的级数吗?我就奇怪如何将一个fortran里的数存到那么多位?有效数字为何会那么多?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-15 15:58:12 | 显示全部楼层
我找到反正弦函数的展开了,但是展开得极慢,50000000000项得到的pai=  3.14155814,还差得远呢。有收敛快的吗?
程序如下,非常简单的一个:
      program arcsin
      double precision pai,xishu
      print *,'tell me the number of terms'
      read (*,*) n
      pai=2.0+1.0/3.0
      xishu=1.0
      do 10 i=2,n
       xishu=xishu*(2*i-1)/2.0/i
       pai=pai+xishu*1.0/(2*i+1)
10    continue
      print *,'pai=',pai
      end

还有,我就不明白windows下的superpai是如何保存pai的数值的,好像fortran里面没有什么可以达到几百万位的有效数字啊。
回复 支持 反对

使用道具 举报

发表于 2005-5-15 16:45:47 | 显示全部楼层
用傅立叶级数展开的办法可行;但本人采用1/4倍率收敛的级数仍然比较缓慢。
可以肯定superpi不仅仅是简单的采用级数展开计算的

我这里有个级数展开式:

  1. pi=3 + (1*1)/(2*3*4) * [ 3 + (3*3)/(4*5*4) *[ 3 + (5*5)/(6*7*4) * [ 3 + (7*7)/(8*9*4) * [ ... ] ] ] ]
复制代码
回复 支持 反对

使用道具 举报

发表于 2005-5-15 16:48:03 | 显示全部楼层
Post by yangjio4849
我找到反正弦函数的展开了,但是展开得极慢,50000000000项得到的pai=  3.14155814,还差得远呢。有收敛快的吗?
程序如下,非常简单的一个:
      program arcsin
      double precision pai,xishu
      print *,'tell me the number of terms'
      read (*,*) n
      pai=2.0+1.0/3.0
      xishu=1.0
      do 10 i=2,n
       xishu=xishu*(2*i-1)/2.0/i
       pai=pai+xishu*1.0/(2*i+1)
10    continue
      print *,'pai=',pai
      end

还有,我就不明白windows下的superpai是如何保存pai的数值的,好像fortran里面没有什么可以达到几百万位的有效数字啊。


你这简单累加绝对不行的,没有任何一种语言可以达到你要求的精度。
可以考虑分段计算,即把小数点后面每n位放在一指定数组段中。
回复 支持 反对

使用道具 举报

发表于 2005-5-15 18:13:56 | 显示全部楼层
贴两个算pi的小程序,采用普遍的傅立叶级数展开方法,不同之处是采用的级数。速度是绝对不如superpi的,仅供参考。使用时请保留著作权信息。

程序一:

  1. /*************************************************************************************************************

  2.         pi值计算程序 pi_v1

  3.         作者:welans @ linuxsir.cn ,2005.5. Copyright reserved

  4.         测试平台:Linux2.6.11-nitro2 + gcc3.4.3 @ AthlonXP1600+, 1G DDR266


  5.         简介:

  6.                 计算圆周率pi到小数点后约5.5万位精度

  7.                 根据公式 pi=3 + (1*1)/(2*3*4) * [ 3 + (3*3)/(4*5*4) *[ 3 + (5*5)/(6*7*4) * [ 3 + (7*7)/(8*9*4) * [ ... ] ] ] ]       

  8.                 每STEP计算8位,每计算8位需占用14个unsigned long long int型数组单元

  9.        
  10.         本地速度评估:5000位小于1秒,50000位小于50秒( 比起super pi 差远了 :-< )



  11.         输入:需计算的圆周率位数,要求小于55000,不保证55000以后的精度。

  12.         输出:计算得到的圆周率结果保存到文件'pi.dat'中。

  13.        

  14.         编译:gcc pi.c -o pi -O3
  15. ************************************************************************************************************/

  16. #include <stdio.h>



  17. #define MIN_LEN 8

  18. #define WIDTH        8

  19. #define STEP 14



  20. int ACC_CORRECT(int acc)

  21. {

  22.         if(acc<MIN_LEN || acc% WIDTH)

  23.         {

  24.                 printf("Accuracy length should be a multiple of %d and no less than %d!\n",WIDTH,MIN_LEN);

  25.                 return 0;

  26.         }

  27.         else return 1;

  28. }



  29. int main()

  30. {

  31.          int ACCURACY_LEN;           // default accuracy length.

  32.          int MAX;                           // size of the array.

  33.          unsigned long long int *a;                           // pointer of the array.

  34.          unsigned long long int i,m,t,k,d,g=30000000;

  35.        

  36.         FILE *fp=NULL;
  37.         if((fp=fopen("pi.dat","wb"))==NULL)

  38.         {

  39.                 printf("Can not create 'pi.dat'!\n");

  40.                 return -1;

  41.         }


  42.         do

  43.         {

  44.                 printf("Input accuracy length:");

  45.                 scanf("%d",&ACCURACY_LEN);

  46.         }

  47.         while( !ACC_CORRECT(ACCURACY_LEN));



  48.         MAX=(ACCURACY_LEN*STEP)/WIDTH;

  49.         a= malloc(MAX*sizeof(unsigned long long int));



  50.         // main procedure for computing pi.

  51.         for(i=0;i<MAX;i++) a[i]=30000000;

  52.         for(m=MAX;m>0;m-=STEP)

  53.         {

  54.                 for (t=0,i=m-1;i>0;i--)

  55.                 {

  56.                         t+=a[i]*100000000;

  57.                         k=i*(i<<4)+(i<<3);

  58.                         a[i]=t%k;

  59.                         d=(i<<1)-1;

  60.                         t=t/k*d*d;

  61.                 }

  62.                 fprintf(fp,"%.8d ",g+t/100000000);

  63.                 g=t%100000000;

  64.         }       

  65.         //end of computing pi

  66.         fprintf(fp,"\n");
  67.         printf("\nResults saved to 'pi.dat'!\n");

  68.         fclose(fp);

  69.         free(a);

  70.         return 0;

  71. }


复制代码


程序二:

  1. /*************************************************************************************************************

  2.         pi值计算程序 pi_v2

  3.         作者:welans @ linuxsir.cn ,2005.5. Copyright reserved

  4.         测试平台:Linux2.6.11-nitro2 + gcc3.4.3 @ AthlonXP1600+, 1G DDR266


  5.         简介:

  6.                 计算圆周率pi到小数点后约30万位精度

  7.                 根据公式 pi=2+1/3*(2+2/5*(2+3/7*(2+4/9*(2+5/11  .....))))))

  8.         本地速度评估:5000位近1秒,50000位小于70秒,10万位小于5分钟。效率略低于piv1。



  9.         输入:需计算的圆周率位数,理论精度约30万位。

  10.         输出:计算得到的圆周率结果保存到文件'pi.dat'中。

  11.        

  12.         编译:gcc pi.c -o pi -O3
  13. ************************************************************************************************************/

  14. #include <stdio.h>



  15. #define MIN_LEN        8

  16. #define WIDTH                8

  17. #define STEP 27



  18. int ACC_CORRECT(int acc)

  19. {

  20.         if(acc<MIN_LEN || acc% WIDTH)

  21.         {

  22.                 printf("Accuracy length should be a multiple of %d and no less than %d!\n",WIDTH,MIN_LEN);

  23.                 return 0;

  24.         }

  25.         else return 1;

  26. }



  27. int main()

  28. {

  29.         unsigned int ACCURACY_LEN;

  30.         unsigned int MAX ;

  31.         unsigned long long int i,m,t,d,g=20000000;

  32.         unsigned long long int *a;


  33.         FILE *fp=NULL;
  34.         if((fp=fopen("pi.dat","wb"))==NULL)

  35.         {

  36.                 printf("Can not create 'pi.dat'!\n");

  37.                 return -1;

  38.         }


  39.         do

  40.         {

  41.                 printf("Input accuracy length:");

  42.                 scanf("%d",&ACCURACY_LEN);

  43.         }
  44.         while(!ACC_CORRECT(ACCURACY_LEN));


  45.         MAX=ACCURACY_LEN*STEP/WIDTH;

  46.         a= malloc(MAX*sizeof(unsigned long long int));


  47.         for(i=0;i<MAX;i++)a[i]=20000000;

  48.         for(m=MAX;m>0;m-=STEP)

  49.         {

  50.                 for (t=0,i=m-1;i>0;i--)

  51.                 {

  52.                         t+=a[i]*100000000;

  53.                         d=(i<<1)+1;

  54.                         a[i]=t%d;

  55.                         t=t/d*i;

  56.                 }

  57.                 fprintf(fp,"%.8d ",g+t/100000000);

  58.                 g=t%100000000;

  59.         }

  60.        

  61.         printf("\nResult saved to file 'pi.dat'!\n");

  62.         fclose(fp);

  63.         free(a);

  64.         return 0;

  65. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-15 21:04:56 | 显示全部楼层
Post by welans
贴两个算pi的小程序,采用普遍的傅立叶级数展开方法,不同之处是采用的级数。速度是绝对不如superpi的,仅供参考。使用时请保留著作权信息。

程序一:

  1. /*************************************************************************************************************

  2.         pi值计算程序 pi_v1

  3.         作者:welans @ linuxsir.cn ,2005.5. Copyright reserved

  4.         测试平台:Linux2.6.11-nitro2 + gcc3.4.3 @ AthlonXP1600+, 1G DDR266


  5.         简介:

  6.                 计算圆周率pi到小数点后约5.5万位精度

  7.                 根据公式 pi=3 + (1*1)/(2*3*4) * [ 3 + (3*3)/(4*5*4) *[ 3 + (5*5)/(6*7*4) * [ 3 + (7*7)/(8*9*4) * [ ... ] ] ] ]       

  8.                 每STEP计算8位,每计算8位需占用14个unsigned long long int型数组单元

  9.        
  10.         本地速度评估:5000位小于1秒,50000位小于50秒( 比起super pi 差远了 :-< )



  11.         输入:需计算的圆周率位数,要求小于55000,不保证55000以后的精度。

  12.         输出:计算得到的圆周率结果保存到文件'pi.dat'中。

  13.        

  14.         编译:gcc pi.c -o pi -O3
  15. ************************************************************************************************************/

  16. #include <stdio.h>



  17. #define MIN_LEN 8

  18. #define WIDTH        8

  19. #define STEP 14



  20. int ACC_CORRECT(int acc)

  21. {

  22.         if(acc<MIN_LEN || acc% WIDTH)

  23.         {

  24.                 printf("Accuracy length should be a multiple of %d and no less than %d!\n",WIDTH,MIN_LEN);

  25.                 return 0;

  26.         }

  27.         else return 1;

  28. }



  29. int main()

  30. {

  31.          int ACCURACY_LEN;           // default accuracy length.

  32.          int MAX;                           // size of the array.

  33.          unsigned long long int *a;                           // pointer of the array.

  34.          unsigned long long int i,m,t,k,d,g=30000000;

  35.        

  36.         FILE *fp=NULL;
  37.         if((fp=fopen("pi.dat","wb"))==NULL)

  38.         {

  39.                 printf("Can not create 'pi.dat'!\n");

  40.                 return -1;

  41.         }


  42.         do

  43.         {

  44.                 printf("Input accuracy length:");

  45.                 scanf("%d",&ACCURACY_LEN);

  46.         }

  47.         while( !ACC_CORRECT(ACCURACY_LEN));



  48.         MAX=(ACCURACY_LEN*STEP)/WIDTH;

  49.         a= malloc(MAX*sizeof(unsigned long long int));



  50.         // main procedure for computing pi.

  51.         for(i=0;i<MAX;i++) a[i]=30000000;

  52.         for(m=MAX;m>0;m-=STEP)

  53.         {

  54.                 for (t=0,i=m-1;i>0;i--)

  55.                 {

  56.                         t+=a[i]*100000000;

  57.                         k=i*(i<<4)+(i<<3);

  58.                         a[i]=t%k;

  59.                         d=(i<<1)-1;

  60.                         t=t/k*d*d;

  61.                 }

  62.                 fprintf(fp,"%.8d ",g+t/100000000);

  63.                 g=t%100000000;

  64.         }       

  65.         //end of computing pi

  66.         fprintf(fp,"\n");
  67.         printf("\nResults saved to 'pi.dat'!\n");

  68.         fclose(fp);

  69.         free(a);

  70.         return 0;

  71. }


复制代码


程序二:

  1. /*************************************************************************************************************

  2.         pi值计算程序 pi_v2

  3.         作者:welans @ linuxsir.cn ,2005.5. Copyright reserved

  4.         测试平台:Linux2.6.11-nitro2 + gcc3.4.3 @ AthlonXP1600+, 1G DDR266


  5.         简介:

  6.                 计算圆周率pi到小数点后约30万位精度

  7.                 根据公式 pi=2+1/3*(2+2/5*(2+3/7*(2+4/9*(2+5/11  .....))))))

  8.         本地速度评估:5000位近1秒,50000位小于70秒,10万位小于5分钟。效率略低于piv1。



  9.         输入:需计算的圆周率位数,理论精度约30万位。

  10.         输出:计算得到的圆周率结果保存到文件'pi.dat'中。

  11.        

  12.         编译:gcc pi.c -o pi -O3
  13. ************************************************************************************************************/

  14. #include <stdio.h>



  15. #define MIN_LEN        8

  16. #define WIDTH                8

  17. #define STEP 27



  18. int ACC_CORRECT(int acc)

  19. {

  20.         if(acc<MIN_LEN || acc% WIDTH)

  21.         {

  22.                 printf("Accuracy length should be a multiple of %d and no less than %d!\n",WIDTH,MIN_LEN);

  23.                 return 0;

  24.         }

  25.         else return 1;

  26. }



  27. int main()

  28. {

  29.         unsigned int ACCURACY_LEN;

  30.         unsigned int MAX ;

  31.         unsigned long long int i,m,t,d,g=20000000;

  32.         unsigned long long int *a;


  33.         FILE *fp=NULL;
  34.         if((fp=fopen("pi.dat","wb"))==NULL)

  35.         {

  36.                 printf("Can not create 'pi.dat'!\n");

  37.                 return -1;

  38.         }


  39.         do

  40.         {

  41.                 printf("Input accuracy length:");

  42.                 scanf("%d",&ACCURACY_LEN);

  43.         }
  44.         while(!ACC_CORRECT(ACCURACY_LEN));


  45.         MAX=ACCURACY_LEN*STEP/WIDTH;

  46.         a= malloc(MAX*sizeof(unsigned long long int));


  47.         for(i=0;i<MAX;i++)a[i]=20000000;

  48.         for(m=MAX;m>0;m-=STEP)

  49.         {

  50.                 for (t=0,i=m-1;i>0;i--)

  51.                 {

  52.                         t+=a[i]*100000000;

  53.                         d=(i<<1)+1;

  54.                         a[i]=t%d;

  55.                         t=t/d*i;

  56.                 }

  57.                 fprintf(fp,"%.8d ",g+t/100000000);

  58.                 g=t%100000000;

  59.         }

  60.        

  61.         printf("\nResult saved to file 'pi.dat'!\n");

  62.         fclose(fp);

  63.         free(a);

  64.         return 0;

  65. }
复制代码




不错啊,大哥是自己编写的吗?好厉害。
我测试了一下,v1,50000位大概40.973s,v2同样位数大概54.671s,Athlon3000+和512M内存。什么时候把这程序改成fortran的看看。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-16 08:29:13 | 显示全部楼层
这么看来流行的super pi软件是用一种更加高效的级数来做的了?真想知道啊。
回复 支持 反对

使用道具 举报

发表于 2005-5-16 10:25:59 | 显示全部楼层
我不认同。
收敛越快的级数,往往伴随着复杂度的增加,使单步计算的时间复杂度也上升了。
比如:我的v1级数收敛速度是v2的两倍,不过计算消耗时间仅仅略少于v2。

《C数值算法》([A]Numerical Recipes in C,数值计算权威著作)一书中最后一章非典型数值算法中也给出了一个算Pi的程序,程序本身和采用的递推式很复杂,但其程序在我机器上运行效率远低于v1和v2。(限于许可证协议,我不能贴出该程序)

我觉得可以考虑并行计算和分布计算。

附件是一个网络上的图片,不知道其正确性,供参考

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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