您的位置:首页 > 其它

利用字符实现大数除法运算(纯c实现)

2011-07-08 23:20 323 查看
那年还是语言刚入门的我,不知纠结了几多次,才完成了能支持大数的算术四则运算,现在看起来别是一番滋味哈。

算术四则运算中就数除法的实现最为繁杂,基本思路按照除法笔算的步骤进行,计算商时一位一位的进行,当计算某一位商时则不断地与除数相减,得到的相减次数作为本位商的结果,实现代码如下,代码可读性不高,效率有待优化,英雄莫见笑。


/*
* author:Zhanhang
*
* qq:273711460
* E-mail:zhanxinhang@gmail.com
* HomePage:http://blog.csdn.net/zhanxinhang
*/

#include<stdio.h>
#include<string.h>
#include<malloc.h>
//清多余的零
void clz(char r[])
{
if(r[0]=='-')r++; //使r指针向前移一位;
int len = strlen(r);
int i=0,k=0;
if(len<2)return;
if(r[i]=='0')
{
for(;r[k]=='0'&&r[k+1]!='.';k++);
for(;i<len-k;i++)
{
r[i]=r[i+k];
}
r[i]='\0';
}
}
//清除数可不要的小数点
void clDot(char r[])
{
int len = strlen(r);
if(r[len-1]=='.')
r[len-1]=0;
}
//为除计算之用的减法
void dsub(char a[],char b[])
{
int i,alen,blen;
char r,t,jiewei=0;
char *pb ;
alen = strlen(a);
blen = strlen(b);
pb = (char *)calloc(alen,sizeof(char));
//使pb与a位数对齐//
memset(pb,'0',alen);
t = alen;
for(i=blen-1;i>=0;i--)
pb[--t]=b[i];

for(i=alen-1;i>=0;i--) //相减运算
{
t = a[i]-jiewei;
if(t<pb[i]) jiewei=1;
else jiewei = 0;
r = (t+jiewei*10)-pb[i];
a[i] = r+'0';
}
a[alen]='\0';
clz(a);
free(pb);
}
//比较两数的大小
int cmp(const char a[],const char b[])
{
int alen = strlen(a);
int blen = strlen(b);
if(alen>blen)
return 1;
else if(alen == blen)
{
if(strcmp(a,b)>0)
return 1;
if(strcmp(a,b)==0)
return 0;
}
else return -1;
}
//除法计算
void div(const char a[],const char b[],char result[])
{
bool isNegative = false;
char *op1,*pa,*pb,*pr;
int up,alen,blen,adotp,bdotp,i,k,dotp,t,t1,j,quo_size;
/////////////判定符号///////////////
//如果为异号
if((a[0] == '-'||b[0] == '-')&&a[0] != b[0])
result[0] = '-',isNegative = true;

//去除负号
if(a[0] == '-')a++;
if(b[0] == '-')b++;
///////////////////////////////////

alen = strlen(a)-1; //减去一位小数点
blen = strlen(b)-1;

///////获取被除数小数点移位后的位置//////////
adotp = strchr(a,'.')-a;
bdotp = strchr(b,'.')-b;

//计算商小数点位置
dotp = adotp+blen-bdotp;
if(isNegative)dotp++;

//////////准备数据/////////////
op1 = (char *)calloc(alen+blen+1,sizeof(char));
pa = (char *)calloc(alen+blen+1,sizeof(char));
pb = (char *)calloc(blen+1,sizeof(char));
pr = (char *)calloc(alen+blen+1,sizeof(char));

for(i = 0,t=0; i<=alen; i++)
{
if(a[i]!='.')
pa[t++] = a[i];
}
for(;t<dotp-1;t++)
{
pa[t] = '0';
}
for(;t<blen;t++)
{
pa[t] = '0';
}

pa[t] = '\0';
for(i = 0,t=0; i<=blen; i++)
{
if(b[i]!='.')
pb[t++] = b[i];
}
pb[t] = '\0';
clz(pa);
clz(pb);
////////取得被除数的高位数op1,且op1大于被除数b//////////
strncpy(op1,pa,strlen(pb));
if(strcmp(op1,pb)<0)
{
strncpy(op1,pa,strlen(pb)+1);
}

/////计算//////
j = k = strlen(op1);
t1=0;
quo_size = strlen(pa)+1-k; //获取商的长度

while(t1<quo_size)
{
up = 0;
t = cmp(op1,pb);
while(t>=0)
{
dsub(op1,pb);
t = cmp(op1,pb);
up++;
}
pr[t1++] = up+'0';
op1[strlen(op1)]=pa[j++];
clz(op1);
}
quo_size+=50;//加50精度
while(t1<quo_size&&(cmp(op1,(char *)"0")>0))
{
up = 0;
op1[strlen(op1)]='0';
t = cmp(op1,pb);
while(t>=0)
{
dsub(op1,pb);
t = cmp(op1,pb);
up++;
}
pr[t1++] = up+'0';
}
//////////////////////////////

if(isNegative)t=1;
else t=0;
for(i=0;i<=t1;i++)//复制结果并给商加上小数点
{
if(t==dotp) result[t++] = '.';
result[t++]=pr[i];
}

clz(result);
clDot(result);
free(op1);
free(pa);
free(pb);
}
main()
{
char result[500]={0};

div("-9999.","3.",result);
printf("%s\n",result);

div("10000000000000000000000000.","5.",result);
printf("%s\n",result);

div("12345678900.","12345678900.",result);
printf("%s\n",result);

div("1.","3.",result);
printf("%s\n",result);

div("-444.","-2.",result);
printf("%s\n",result);

div("6660.","-3330.",result);
printf("%s\n",result);

div("1.","3333333333333333333333.",result); //bug
printf("%s\n",result);
}

结果:(每一行对应于main中的每一次调用div所得到的结果)



======= welcome to my HomePage(http://blog.csdn.net/zhanxinhang) to have a communication =======
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: