C语言的高精度算法
- 格式:doc
- 大小:92.50 KB
- 文档页数:18
1 高精度计算
一. 加法
先判断出两个数哪个较长,两个数从个位对齐后,从个位数开始相加,先不考虑进位的问题,相加直到较短的数的最高位。接着把较长的数未相加的部分进行赋值。最后在处理进位问题(判断每位上的数是否大于等于10)。
其中要注意的是两数相加,得到的和的位数是否比较长的数的位数大1。和进位问题的处理。
代码:
# include
# include
# include
void add(char* a,char* b,char* c)
{
int i,j,k,max,min,n,temp;
char *s,*pmax,*pmin;
max=strlen(a);
min=strlen(b);
if (max
temp=max;
max=min;
min=temp;
pmax=b;
pmin=a;
}
else
{
pmax=a;
pmin=b;
}
s=(char*)malloc(sizeof(char)*(max+1));
s[0]='0';
for (i=min-1,j=max-1,k=max;i>=0;i--,j--,k--)
s[k]=pmin[i]-'0'+pmax[j];
for (;j>=0;j--,k--)
s[k]=pmax[j];
for (i=max;i>=0;i--)
if (s[i]>'9')
{
s[i]-=10; 3 s[i-1]++;
}
if (s[0]=='0')
{
for (i=0;i<=max;i++)
c[i-1]=s[i];
c[i-1]='\0';
}
else
{
for (i=0;i<=max;i++)
c[i]=s[i];
c[i]='\0';
}
free(s);
}
二. 减法
先考虑减数大于被减数的情况。也是先对齐,再相减,接赋值,最后是处理借位问题(判断每位上的数是否小于0)。
如果减数小于被减数的话,可以用被减数减去减数。最后在结果的前面加个负号就可以了。 4
源代码:
# include
# include
# include
void subtract(char* a,char* b,char* c)
{
int i,j,ca,cb;
ca=strlen(a);
cb=strlen(b);
if (ca>cb||(ca==cb&&strcmp(a,b)>=0))
{
for (i=ca-1,j=cb-1;j>=0;i--,j--)
a[i]-=(b[j]-'0');
for (i=ca-1;i>=0;i--)
if (a[i]<'0')
{
a[i]+=10;
a[i-1]--;
}
i=0;
while (a[i]=='0')
i++;
if (a[i]=='\0')
{
c[0]='0';
c[1]='\0';
}
else
{
for (j=0;a[i]!='\0';i++,j++)
c[j]=a[i];
c[j]='\0';
}
}
else
{
for (i=ca-1,j=cb-1;i>=0;i--,j--)
b[j]-=(a[i]-'0');
for (j=cb-1;j>=0;j--)
if (b[j]<'0')
{ 5 b[j]+=10;
b[j-1]--;
}
j=0;
while (b[j]=='0')
j++;
i=1;
c[0]='-';
for (;b[j]!='\0';i++,j++)
c[i]=b[j];
c[i]='\0';
}
}
三.乘法
注意乘积的最大位数是两个数的位数之和。先相乘,再处理进位问题。
for (i=0;i
for (j=0;j
c[i+j+1]+=(a[i]-'0')*(b[j]-'0');
源代码:
# include
# include
# include
void multiply(char* a,char* b,char* c)
{
int i,j,ca,cb,* s;
ca=strlen(a);
cb=strlen(b);
s=(int*)malloc(sizeof(int)*(ca+cb));
for (i=0;i
s[i]=0;
for (i=0;i
for (j=0;j
for (i=ca+cb-1;i>=0;i--)
if (s[i]>=10)
{
s[i-1]+=s[i]/10;
s[i]%=10;
}
i=0;
while (s[i]==0)
i++;
for (j=0;i
c[j]=s[i]+'0';
c[j]='\0';
free(s);
}
四. 除法
高精度的除法最后的结果整数部分和余数。其中被除数一般是计算机可以表示的整数。
源代码:
# include
# include
# include
int dividor(char* a,int b,char* c)
{
int i,j,temp=0,n;
char* s;
n=strlen(a); 7 s=(char*)malloc(sizeof(char)*(n+1));
for (i=0;a[i]!=0;i++)
{
temp=temp*10+a[i]-'0';
s[i]=temp/b+'0';
temp%=b;
}
s[i]='\0';
for (i=0;s[i]=='0'&&s[i]!='\0';i++);
if (s[i]=='\0')
{
c[0]='0';
c[1]='\0';
}
else
{
for (j=0;s[i]!='\0';i++,j++)
c[j]=s[i];
c[j]='\0';
}
free(s);
return temp; 8 }
例1( ZOJ-1205):
在22世纪,科学家发现有外星人的存在。他们十分喜欢数学。每年他们都举行 ACM比赛。题目是计算2个100位数的和。谁用的时间最少,谁就获胜。
今年他们邀请我们去参加他们的比赛。而你幸运的成为我们的代表去参赛。现在你唯一的问题是编写一个小程序去计算2个数的和。但是他们的数是20进制。他们的数由0-9和a-j(代表10-19)表示。
输入:
成对的给出一些他们用20进制表示的数,每个数占一行。而且每个数不会超过100位。
输出:
对每一对数,在一行上输出他们的和(还是用20进制表示)。
分析:
两数相加,对齐后,从最后一位开始。先把各个位上的数转化成10进制的数,再相加。最后把各个位上的数转化成20进制的数。注意2个数的和,最后位数可能跟较长的数相同,可能大1。
源代码: 9 # include
# include
int main()
{
int i,min,max,j;
char a[101],b[101],c[102],*pmin,*pmax;
while (scanf("%s %s",a,b)==2) //判断输入是否结素
{
if (a[0]=='0'&&b[0]=='0') //可能有点多余
printf("0\n");
else
{
for (i=0;i<101;i++)
c[i]='0';
min=strlen(a); /*
max=strlen(b); 求每个数的长度
if (min<=max) 把较长的数的地址赋给pmax
{ 较短的赋给pmin
pmin=a; 这样可以节省考虑的情况
pmax=b; */
}
else
{
i=min;
min=max;
max=i;
pmin=b;
pmax=a;
}
i=j=max;
c[max+1]='\0';
for (min--,max--;min>=0;i--,min--,max--) /*
{ 先将2个数从最后一位对齐
if (pmin[min]>='a') 在从最后一位开始相加