/***************************************************************************************************************
我加入下面几个 define 是为了改动数据类型方便。
用
#define PART 12
#define DATA 1000000000000
#define TYPE UINT64
定义的方式计算竟然没有用
#define PART 4
#define DATA 10000
#define TYPE UINT
定义的方式计算快,是因为我的系统不是64位的吗???
****************************************************************************************************************/
#define JISIWEI 3
#define PART 4
#define DATA 10000
#define TYPE UINT
//#define PART 12
//#define DATA 1000000000000
//#define TYPE UINT64
/*******************************************************************************************************
基本原理:
x=z=2;a=1;b=3;
while(z*=a/b)
{ x+=z;a++;b+=2;
}
计算结果在 x 中(相关知识去看高数^O^)
/*******************************************************************************************************
上面的方法中有这样一个缺点:当 z 值很小时,z 值的前面许多位(高位)已经为0了,但是我们还在按步就班地做乘、除、加这样的无用功。对已经为0的高位,我们完全可以不用再管了,因为 z 是越来越小的。这样做可以省一半的时间。
优化算法:
*******************************************************************************************************/
void CPIDlg::OnButton2()
{ const int DISPCNT=GetDlgItemInt(IDC_WEISHU,NULL,TRUE)+2;
const int ARRSIZE=DISPCNT+DISPCNT/50+JISIWEI; //计算到ARRSIZE位数,最后若干位不准,所以只显示前DISPCNT位数
char c,*x=new char[ARRSIZE], *z=new char[ARRSIZE+1],*ix,*iz,*ie,*i0; //x[0] x[1] . x[2] x[3] x[4] .... x[ARRSIZE-1]
int a=1, b=3, d;
memset(x,0,ARRSIZE);
memset(z,0,ARRSIZE);
*(x+1) = *(i0=z+1) = 2; // x[1]和z[1]表示右起第一位数,也就是最高位
z[ARRSIZE]=10;
DWORD time1=GetTickCount();
do
{ // z *= a/b;把此计算分成两步:先算z*=a,再算z/=b
//z*=a的计算,z[i]中每字节存一位数字,从低位向高位乘。
for(d=0,iz=z+ARRSIZE-1;i0<=iz;iz--)
{ *iz = (d += (*iz)*a) % 10; //当前位乘a再加上低位的进位d//个位放在z[i]中
d /= 10; //进位放在d中
}
while(d)
{ *iz-- = d % 10; //个位放在z[i]中
d /= 10; //进位放在d中
}