- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
楼主 |
发表于 2008-4-16 21:31:16
|
显示全部楼层
本帖给出使用HugeCalc,使用7#楼算法计算e的一个实现,使用该程序,在PIV2.6上,计算10万位e需0.412秒,计算100万位e需要5.06秒。- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
-
- #include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h" // 公共接口
- #include "../../../HugeCalc_API/CppAPI/Include/HugeInt.h" // 10进制系统
-
- #pragma message( "automatic link to ../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
- #pragma comment( lib, "../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
-
-
- #define integer CHugeInt
- #define USE_HUGE_CALC_DIV
-
- #if 0
- # define MODIFIED_BY_GxQ
- #endif
-
- #define MIN_SPLIT 32
- static DWORD g_divTime=0;
-
- // 计算e的一个快速的版本,采用2分法,尽量使用以及大数乘法,
- // 收尾阶段采用大数除法
-
-
- //欲达到n位有效数字,需使得 n!> 10^n
- //返回计算d位有效数字所需的最大的n
-
- static UINT32 maxNForCalcE(int d)
- {
- double f=d*log(10);
- double r=0;
- UINT32 i=0;
- //loop untill log(n!)>log(10^d)
- do
- {
- i++; r += log(i);
- }while (r<f);
- return i;
- }
-
- // calc 1/n1 + 1/(n1*(n1+1)) + 1/(n1*(n1+1)+(n1+2))+ 1/(n1*(n1+1)+(n1+2)+...m)
- // 计算结果为 p/q
- // for example:
-
- // 1/6 + 1/6*7 + 1/6*7*8 + 1/6*7*8*9
- // = 7*8*9/6*7*8*9 + 8*9/6*7*8*9 + 9/6*7*8*9 + 1/ 6*7*8*9
- // calculate
- // q=6*7*8*9, p=1 + 9+ 8*9 + 7*8*9
- // steps:
- // step1: p=1, q=1;
- // step2: q*=9, p+=q , q=9, q=1+9
- // step3: q*=8, p+=q , q=9*8, q=1+8*9
- // step4: q*=7, p+=q , q=9*8*7, q=1+ 8*9 + 7*8*9
- // step5: q*=6
- static void calc_Frac_Sum(UINT32 n1,UINT32 n2, integer &p,integer &q)
- {
- p=(UINT32)1;
- q=(UINT32)1;
- for ( UINT32 i=n2;i>n1;i--)
- {
- q*=i;
- p+=q;
- }
- q*=i;
- }
-
- #ifndef MODIFIED_BY_GxQ
- void splitCalc(UINT32 n1,UINT32 n2, integer &p,integer &q)
- {
- if (n2-n1<=MIN_SPLIT)
- {
- calc_Frac_Sum(n1,n2,p,q);
- }
- else
- {
- integer p1,q1,p2,q2;
- splitCalc( n1, (n1+n2)/2, p1,q1);
- splitCalc( (n1+n2+2)/2 ,n2, p2,q2);
- p=p1*q2 + p2;
- q=q1*q2;
- }
- }
- #else
- integer tmp;
- void splitCalc(UINT32 n1,UINT32 n2, integer &p,integer &q)
- {
- if (n2-n1<=MIN_SPLIT)
- {
- calc_Frac_Sum(n1,n2,p,q);
- }
- else
- {
- integer q1,p2;
- splitCalc( n1, (n1+n2)/2, p, q1);
- splitCalc( (n1+n2+2)/2 ,n2, p2,q );
-
- // ( p *= q ) += p2;
- tmp.Swap( p );
- p.Mul( tmp, q ) += p2;
-
- // q *= q1;
- tmp.Swap( q );
- q.Mul( tmp, q1 );
- }
- }
- #endif
-
- void calc_e_3(integer *r, int len )
- {
- UINT32 n;
- int shift;
- integer p,q;
-
- n= maxNForCalcE(len)+2;
- splitCalc(1,n,p,q); // p/q= 1/1!+1/2!+1/3!+1/4!+...
-
- p+=q; // p/q +=1 // e= p/q= 1 + 1/1!+1/2!+1/3!+1/4!+...
- shift=(len+8)/9*9; //get upbounds get times of 9
- p.DecLShift(shift); //增加有效数字
-
- g_divTime=GetTickCount();
- #ifdef USE_HUGE_CALC_DIV
- #ifndef MODIFIED_BY_GxQ
- p=p /q;
- #else
- p /= q;
- #endif
- #else
- {
- void inverse( const integer *s, integer *pResult,int len);
- integer t;
- inverse(&q,&t,len);
- p *=t;
- }
- #endif
- g_divTime=GetTickCount()-g_divTime;
- *r=p;
- }
-
- void calc_e3_main()
- {
- int len;
- integer e;
- char *pBuff=NULL;
- const char *pTmp;
- char fileName[32];
- FILE *fp=NULL;
-
- printf("calculate e (fast version1)\n");
- #ifdef MODIFIED_BY_GxQ
- printf("defined 'MODIFIED_BY_GxQ'\n");
- #endif
- while (true)
- {
- printf("How many digital is needed(0 will exit)?");
- scanf("%d",&len);
- if (len==0)
- break;
-
- HugeCalc::EnableTimer( TRUE );
- HugeCalc::ResetTimer();
-
- calc_e_3(&e,len);
-
- // 记录计算耗时
- UINT32 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
- printf("计算用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);
- if (g_divTime>=2)
- {
- printf("其中除法用时 %f秒\n", (double)g_divTime/1000.00);
- }
- //----------------------------------------
- HugeCalc::EnableTimer( TRUE );
- HugeCalc::ResetTimer();
-
- pBuff=new char[e.GetDigits()+3];
- if (pBuff==NULL)
- goto thisExit;
-
- pTmp= e.GetStr(FS_NORMAL);
- strcpy(pBuff+1,pTmp);
-
- pBuff[0]=pBuff[1];
- pBuff[1]='.'; //插入小数点
- pBuff[len+2]=0; //去掉多余的数字
-
- sprintf(fileName,"e3_%d.txt",len);
- FILE *fp=fopen(fileName,"wb");
- fwrite(pBuff,len+2,1,fp);
- fclose(fp); fp=NULL;
- delete[] pBuff; pBuff=NULL;
-
- u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
- printf("输出到文件用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);
- }
-
- thisExit:
- if (fp!=NULL)
- {
- fclose(fp); fp=NULL;
- }
- if (pBuff!=NULL)
- {
- delete[] pBuff; pBuff=NULL;
- }
- }
复制代码
[ 本帖最后由 liangbch 于 2008-4-17 14:34 编辑 ] |
|