- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
发表于 2016-5-2 20:15:48
|
显示全部楼层
本站帖子 http://bbs.emath.ac.cn/thread-143-1-10.html 讨论了使用牛顿迭代法求高精度平方根的方法,可惜在论坛转移的过程中,代码无法下载。我在我的电脑上搜索了下,找到一份代码,不知道有没有问题,见下。
- // sqrt2.cpp : Defines the entry point for the console application.
- //
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <iostream.h>
- #include "../../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeCalc.h" // 公共接口
- #include "../../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeInt.h" // 10进制系统
- #include "../../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeIntX.h" // 16进制系统
- #pragma message( "automatic link to ../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
- #pragma comment( lib, "../../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
- #define integer CHugeInt
- #define TEN9 1000000000
- /*
- sqrt(a) 算法:
-
- step1: 得到一个 1/sqrt(a) 近似值 x0
- step2: x[n+1]= 3/2*x[n] + a/2 x[n]^3
- 另一个形式: ( x[n+1]= x[n] + x[n] ( 1/2- a/2 *x[n]^2)
- 不断计算step2,x[n+1]精度逐步提高,每次迭代精度提高一倍。
- 最后:计算 x[n+1]* a 得到 sqrt(a)
- */
- double int_sqrt_demo(int n)
- {
- double x0;
- double x1;
- double c0,c1;
-
- c0=0.5;
- c1=double(n)/2;
- x0= 1 /sqrt( n );
- x0= floor(x0 * 10000.0) /10000; //取前4位有效数字
-
- while (true)
- {
- x1= x0 + x0 * (c0- c1 * x0 * x0);
- if ( (x1- x0)/x0 <1e-15)
- {
- break;
- }
- x0=x1;
- }
- return double(n) * x1;
- }
- int dig2Unit(int n)
- {
- return (n+8)/9;
- }
- void sqrt_proc( double n, integer *x,int lmt_pre[],double limitLen)
- {
- int i=0;
- char *pBuff=NULL;
- const char *pTmp;
- double esp=1e-15;
- UINT32 digLen; //数字个数
- integer x0;
- integer x1;
- integer t1;
- integer t2;
-
- integer c0;
- integer c1;
-
- {
- unsigned int n_01,n_02;
- n/=2;
- c0= (TEN9/2); // c0=0.5;
- n_01= UINT32(n);
- n_02= UINT32((n-n_01+esp)*TEN9);
- c1 = n_01;
- c1 *= TEN9;
- c1 += n_02; // c1=double(n)/2;
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[c1.GetDigits()+2];
- pTmp= c1.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("c1=%s\n",pBuff);
-
- #endif
- }
-
- x0= *x;
- i=0;
- digLen=x0.GetDigits();
- while (true)
- {
- #ifdef _DEBUG
- printf("第%d次迭代\n",i+1);
- #endif
-
- if (i>0 && digLen -lmt_pre[i]>=9)
- {
- int shift= (digLen-lmt_pre[i])/9*9;
- x0.DecRShift( shift ); //丢弃多于的数字
- digLen=x0.GetDigits();
- }
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[x0.GetDigits()+2];
- pTmp= x0.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("x0=%s\n",pBuff);
- #endif
-
- t1.Pow( x0,2); //t1= x0 * x0
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[t1.GetDigits()+2];
- pTmp= t1.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("t1=%s\n",pBuff);
- #endif
-
- // x1= x0 + x0 * (c0- c1 * x0 * x0);
- // c0=0.5;
- // c1=double(n)/2;
- t1 *= c1; // t1= c1* x0 * x0
- t1.DecRShift(9);
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[t1.GetDigits()+2];
- pTmp= t1.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("t1=%s\n",pBuff);
- #endif
- t2=c0;
- t2.DecLShift( dig2Unit(digLen)*2*9-9); //扩展数位
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[t2.GetDigits()+2];
- pTmp= t2.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("t2=%s\n",pBuff);
- #endif
- t2-=t1; // t2= (c0- c1* x0 * x0);
- t2 *= x0; // t2= x0 * (c0- c1* x0 * x0);
- t2.DecRShift(dig2Unit(digLen)*9);
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[t2.GetDigits()+2];
- pTmp= t2.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("t2=%s\n",pBuff);
-
- #endif
- x0.DecLShift( dig2Unit(digLen)*9 ); //扩展x0长度
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[x0.GetDigits()+2];
- pTmp= x0.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("x0=%s\n",pBuff);
- #endif
- x1= x0 + t2; // x1= x0 + x0 * (c0- c1 * x0 * x0);
-
- #ifdef _DEBUG
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[x1.GetDigits()+2];
-
- pTmp= x1.GetStr(FS_NORMAL);
- strcpy(pBuff,pTmp);
- printf("x1=%s\n",pBuff);
- #endif
- x0=x1;
- digLen= x0.GetDigits();
- if ( digLen >= limitLen)
- {
- break;
- }
- i++;
- }
-
- *x= x0;
- if (pBuff!=NULL)
- {
- delete[] pBuff;
- }
- }
- //高精度整数平方根
- void int_sqrt(int num, int dig,char *fileName)
- {
- double fNum;
- double fLen;
- int e; //100^e 表示需要把被开方数缩小 100^e,最终结果需要扩大10^e倍
- int i,k;
- int tmp;
-
- int lmt_pre[32]; //第i次迭代最低要求精度,单位10进制位
-
- UINT32 i0;
- char *pBuff=NULL;
- const char *pTmp;
- HugeCalc::EnableTimer( TRUE );
- HugeCalc::ResetTimer();
-
- integer x;
-
- tmp=num;
- e=0;
- while (tmp>=100)
- {
- tmp /= 100;
- e++;
- }
- fNum= (double)(num) / pow(100.00,e);
- k=0;
- fLen=dig+18;
- while (fLen >=9)
- {
- fLen /= 2.0;
- k++;
- }
- for (i=0;i<=k;i++)
- {
- lmt_pre[i]=(int)(ceil(fLen));
- fLen *=2;
- }
- i0= (UINT32)floor(1.0/sqrt(fNum) * TEN9+0.5);
-
- if (i0>=TEN9)
- i0=TEN9-1;
- x=i0;
- sqrt_proc(fNum, &x,lmt_pre,dig+18);
- x *= integer(num);
- if ( pBuff!=NULL)
- { delete[] pBuff; }
- pBuff=new char[x.GetDigits()+3];
-
- pTmp= x.GetStr(FS_NORMAL);
- strcpy(pBuff+1,pTmp);
-
- int intLen= (int)ceil(log10(sqrt(num))); //计算整数部分的数字个数
-
- memcpy(pBuff,pBuff+1,intLen);
- pBuff[intLen]='.'; //插入小数点
- pBuff[dig+1]=0; //去掉多余的数字
- // 记录计算耗时
- UINT32 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
- double ftime= u32Timer_Calc;
- printf("计算用时 %.6f 秒\n", ftime/1000000.0);
- HugeCalc::EnableTimer( TRUE );
- HugeCalc::ResetTimer();
- FILE *fp=fopen(fileName,"wb");
- fwrite(pBuff,dig+1,1,fp);
- fclose(fp);
- u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
- ftime= u32Timer_Calc;
- printf("输出到文件用时 %.6f 秒\n", ftime/1000000.0);
- delete[] pBuff;
- pBuff=NULL;
- }
- void test_demo()
- {
- double f1=int_sqrt_demo(2);
- double f2=int_sqrt_demo(3);
- double f3=int_sqrt_demo(10);
- double f4=int_sqrt_demo(1000);
- }
- void nums_sqrt()
- {
- int n;
- int dig;
- char fileName[100];
- printf("calc sqrt(n)\n");
-
- while (true)
- {
- printf("n=?(0 exit)");
- scanf("%d",&n);
-
- if (n==0 )
- break;
- printf("how many digital is needed?");
- scanf("%d",&dig);
- if (dig<=0)
- break;
- sprintf(fileName,"sqrt_%d_%08d.txt",n,dig);
- int_sqrt(n,dig,fileName);
- }
- }
- int main(int argc, char* argv[])
- {
- //test_demo();
- nums_sqrt();
- return 0;
- }
复制代码 |
|