您的位置:首页 > 其它

【算法】大整数加法

2012-07-29 19:42 183 查看

1.算法描述

为了表示大整数,一般采用字符数组,这样可以表示更多位的整数。在实现大整数加法时,可模拟小学生列竖式。首先,位对齐,两个大整数的个位对个位、十位对十位、百位对百位……然后,按位相加,如果满十,则置进位为1。两个大数的高位相加时,要加上进位。

长度为n的字符数组在表示大整数时,[0]表示大整数的最高位,[n-1]表示大整数的最低位(即个位)。所以,在位对齐时,处理比较麻烦。

2.问题

2.1 九度OJ 1198

题目要求:实现一个加法器,使其能够输出a+b的值。

源代码:

1198Accepted
908KB2595B120MSC / 代码
#include <stdio.h>
#include <string.h>

int main()
{
char a[1000],b[1000],c[1000],carry[1001];     //carry[i]表示进位
int i,j,k,temp,a_length,b_length;

while(~scanf("%s%s",&a,&b))
{
a_length=strlen(a);
b_length=strlen(b);

if(a_length<b_length)                        //a的位数比b的位数少
{
memset(carry,'0',b_length+1);
for(i=a_length-1,j=b_length-1,k=0;i>=0;i--,j--,k++)
{
temp=a[i]+b[j]+carry[k]-96;
if(temp>57)
{
temp=temp-10;
carry[k+1]='1';
}
else carry[k+1]='0';
c[k]=(char) temp;
}
for(j=b_length-a_length-1,k=a_length;j>=0;j--,k++)
{
temp=b[j]+carry[k]-48;
if(temp>57)
{
temp=temp-10;
carry[k+1]='1';
}
else carry[k+1]='0';
c[k]=(char) temp;
}
if(carry[b_length]=='1')               //判断最高位是否有进位
{
c[b_length]='1';
c[b_length+1]='\0';
}
else c[b_length]='\0';

}

else if(a_length==b_length)
{
memset(carry,'0',a_length+1);
for(i=a_length-1,k=0;i>=-0;i--,k++)
{
temp=a[i]+b[i]+carry[k]-96;
if(temp>57)
{
temp=temp-10;
carry[k+1]='1';
}
else carry[k+1]='0';
c[k]=(char) temp;
}
if(carry[a_length]=='1')
{
c[a_length]='1';
c[a_length+1]='\0';
}
else c[a_length]='\0';
}

else
{
memset(carry,'0',b_length+1);
for(i=a_length-1,j=b_length-1,k=0;j>=0;i--,j--,k++)
{
temp=a[i]+b[j]+carry[k]-96;
if(temp>57)
{
temp=temp-10;
carry[k+1]='1';
}
else carry[k+1]='0';
c[k]=(char) temp;
}
for(i=a_length-b_length-1,k=b_length;i>=0;i--,k++)
{
temp=a[i]+carry[k]-48;
if(temp>57)
{
temp=temp-10;
carry[k+1]='1';
}
else carry[k+1]='0';
c[k]=(char) temp;
}
if(carry[a_length]=='1')
{
c[a_length]='1';
c[a_length+1]='\0';
}
else c[a_length]='\0';

}

int c_length=strlen(c);
for(i=c_length-1;i>=0;i--)
printf("%c",c[i]);
printf("\n");
}
return 0;
}


2.2 POJ 1503

求:输入n个大数之和。

用int数组sum存放运算结果,通过sum[ i ]>10判断是否有进位。

WA了几次,看Discuss,原来数组要开到105。

源代码:

1503Accepted116K0MSC780B2013-08-26 10:45:55
#include "stdio.h"
#include "string.h"

#define MAX 105

int main()
{
int sum[MAX];
int i, j, leading_zero, ch_length;
char ch[MAX];

memset(sum,0,sizeof(sum));

while(scanf("%s",&ch))
{
ch_length=strlen(ch);
if(ch_length==1&&ch[0]=='0')              //judge the end of input
break;
for(i=MAX-1,j=ch_length-1; j>=0; i--,j--)
sum[i]+=ch[j]-'0';

for(i=MAX-1,j=ch_length-1; j>=0; i--,j--)   //deal with the carry
{
if(sum[i]>=10)
{
sum[i]%=10;
sum[i-1]++;
}
}
}

/*deal with leading zero, output the sum*/
for(i=0,leading_zero=0; i<MAX; i++)
if(sum[i]!=0)
{
leading_zero=i;
break;
}
for(i=leading_zero;i<MAX;i++)
printf("%d",sum[i]);
printf("\n");

return 0;
}


2.3 POJ 2413

求:区间[a, b]上的fibonacci数有几个。

思路:用大整数加法求出前490个fibonacci数(其实,第480个fibonacci数就有100位了);用二分查找,找出a,b在fibonacci数组的位置,即可求出fibonacci数的个数。

用指针变量做形参才能改变变量的值,比如BinarySerach(, , ,*flag)而不是BinarySerach(, , ,flag)。二分查找没写好,WA了几次。代码参考十三年草 ,做了一些优化。

源代码:

2413Accepted168K0MSC2337B2013-08-27 20:31:16
#include "stdio.h"
#include "string.h"

#define MAX 105
#define MAXnum 490

/*store fibonacci numbers*/
char fibonacci[MAXnum][MAX];

/*big inter addition*/
void Add(char *a, char *b, char *sum)
{
int i,j,k,leading_zero;
int temp[MAX];
memset(temp,0,sizeof(temp));

for(i=strlen(a)-1,j=MAX-1;i>=0;i--,j--)
temp[j]=a[i]-'0';
for(i=strlen(b)-1,k=MAX-1;i>=0;i--,k--)
temp[k]+=b[i]-'0';

/*标记前导0的结束位置*/
leading_zero=j<k?j:k;

/*deal with carry*/
for(i=MAX-1;i>=leading_zero;i--)
{
if(temp[i]>=10)
{
temp[i]%=10;
temp[i-1]++;
}
}

/*deal with leading zero*/
if(temp[leading_zero]==0)
leading_zero++;

for(i=0,j=leading_zero;j<=MAX-1;i++,j++)
sum[i]=temp[j]+'0';
}

/*compute fibonacci numbers*/
void ComputeFibo()
{
int i;
memset(fibonacci,'\0',sizeof(fibonacci));
strcpy(fibonacci[1],"1");
strcpy(fibonacci[2],"2");

for(i=3;i<MAXnum;i++)
Add(fibonacci[i-1],fibonacci[i-2],fibonacci[i]);
}

/*compare two strings*/
int Compare(char *a, char *b)
{
int a_length, b_length;
a_length=strlen(a);
b_length=strlen(b);
if(a_length==b_length)
return strcmp(a,b);
else
return a_length>b_length?1:-1;
}

/*当a不是fibonacci数时,二分查找返回的是第一个比a大的fibonacci数
flag标记查找元素a是否属于fibonacci数组*/
int BinarySearch(int low, int high, char *a, int *flag)
{
int pivot, comp;
while(low<=high)
{
pivot=(low+high)/2;
comp=Compare(a,fibonacci[pivot]);
if(comp==0)
{
*flag=1;
return pivot;
}
else if(comp<0)
high=pivot-1;
else
low=pivot+1;
}
return low;
}

int main()
{
char a[MAX], b[MAX];
int a_length, b_length, a_start, b_start;
int left_flag, right_flag;

ComputeFibo();
while(scanf("%s%s",&a,&b))
{
left_flag=0; right_flag=0;
a_length=strlen(a); b_length=strlen(b);

if(strcmp(a,"0")==0&&strcmp(b,"0")==0)
break;

a_start=BinarySearch(1,MAXnum-1,a,&left_flag);
b_start=BinarySearch(a_start,MAXnum-1,b,&right_flag);

if(right_flag)
printf("%d\n",b_start-a_start+1);
else
printf("%d\n",b_start-a_start);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: