⼤整数专题之⼤整数相加【附过程详解+两种⽅法+测试数据
+例题】
⼤数问题,其实就是模拟运算,因为系统⾃带的int、long、bouble(double虽然可以表⽰很⼤的数,但那是使⽤的科学记数法,保存的数值的精度是有限的,最⼤精度只有⼗⼏位,后⾯的数字就保存不了了,会全变成0)这些类型均⽆法容纳百位乃⾄千位的⼤数字,从⽽⼿动模拟的运算过程,我们⼀般使⽤字符串来表⽰这样的超⼤数字。
测试数据:
/*
987654321987654321 987654321987654321
1975308643975308642
9999999999999999999 9
100000000000000000008
*/
基本上这两组测试数据过了就没啥问题了。
⽅法⼀:使⽤三个字符串【两个⽤于存储输⼊的待计算的⼤整数,⼀个⽤于过程计算中的临时存储】+⼀个整型数组【为了进位⽅便⽽设置的数组】
#include<stdio.h>
#include<string.h>
int main()
{
int n,i,j,count=0,num1[1006],len1,len2,len_max,result,t;
char str1[1006],str2[1006],str3[1006];
scanf("%d",&n);
while(n--)
{
memset(num1,0,sizeof(num1));//把整型数组清零
scanf("%s %s",str1,str2);
/*如果把它们看成整形数据,⽐如输⼊的是13和87,我们知道其结果是100
现在我们是把他们看成字符串了,因此:
对于13来说,str1[0]=1,str1[1]=3
对于87来说,str2[0]=8,str2[1]=7
我们在计算时,只需要按⼩学的数学知识,让他们从低位到⾼位,每⼀位进⾏相加即可,
满⼗进⼀,⽐如3+7=10,那么我们可以把字符数组相加的数据存储在整型数组中,
num1[0]=str[1]+str2[1]=3+7=10(注意是把字符数组倒序相加,因为字符数组下标最⼤的数字是个位)
因为num1[0]的结果⼤于等于10,我们需要满⼗进⼀,
操作⽅法为:num1[0]=num1[0]-1;
num1[1]=num1[1]+1;(之前记得把num1中的元素全部清零)
num1[1]=str1[0]+str2[0]=1+8=9,⼜因为个位满⼗进⼀,所以,num1[1]=num1[1]+1=10,这⾥⼗位有满⼗了
所以需要向百位进⼀,具体进位⽅式,我就不写了吧,和个位进⼗位⼀样
然⽽,那种两个数字的位数⼀样,还⽐较好办,对于两个数字位数不⼀样的怎么办呢,
我们可以加0补齐嘛,然后就转化成了刚才两个数字位数⼀样的问题了。
⽐如:12 和998,我们可以把12补成012,998就不变了,
我们只需要把数字位数最短的那个数字的位数补成和数字位数最长的那个数字的位数⼀样就⾏了
scanf输入整型数组12 和998,我们知道结果是1010
对于12说,str1[0]=1,str1[1]=2
对于998来说,str2[0]=9,str2[1]=9,str2[2]=8
对于998来说,str2[0]=9,str2[1]=9,str2[2]=8
在进⾏补0的时候,我们需要特别注意:对于12,千万不能把str[2]补成0,
因为那样⼀补位的话,就把12变成了120了,
我们可以再定义⼀个字符数组str3,先把str3[1]弄成0,然后再把str2中的每⼀个元素挨个复制到str3中就⾏了        这样就达到把12补成012的⽬的了
同时为了接下来的⽅便,我们补完0之后,可以把str3中的每⼀位元素,再挨个复制到str2中
*/
len1=strlen(str1);
len2=strlen(str2);
/*for(i=0;i<len1;i++)//⽤于显⽰输⼊的数字,再转化成字符串之后,字符数组的下标与每⼀位数字的关系
{
printf("str1[%d]=%c\n",i,str1[i]);
}
putchar(10);//打印换⾏,换⾏的ASCII代码是10
for(i=0;i<len2;i++)
{
printf("str2[%d]=%c\n",i,str2[i]);
}*/
if(len1>=len2)
{
result=1;//⽤于观测哪个数字位数⽐较长
len_max=len1;
for(i=len2,j=0;i<len_max;i++,j++)//先补零
{
str3[j]='0';
}
for(i=0;i<len2;i++,j++)//再把str2中的元素依次复制到补零位之后
{
str3[j]=str2[i];
}
for(i=0;i<len_max;i++)//为了后续⽅便,可以把str3⾥的元素再逐位全部转到str2⾥
{
str2[i]=str3[i];
}
}
else
{
result=0;
len_max=len2;
for(i=len1,j=0;i<len_max;i++,j++)
{
str3[j]='0';
}
for(i=0;i<len1;i++,j++)
{
str3[j]=str1[i];
}
for(i=0;i<len_max;i++)
{
str1[i]=str3[i];
}
}
len_max=len1>=len2?len1:len2;
for(i=len_max-1,j=0;i>=0;i--,j++)
for(i=len_max-1,j=0;i>=0;i--,j++)
{
num1[j]=str1[i]-'0'+str2[i]-'0';//把字符数组中的元素从个位到最⾼位依次计算
}
for(j=0;j<len_max;j++)
{
if(num1[j]>=10)
{
num1[j+1]=num1[j+1]+1;//从个位到最⾼位依次排查,看是否有⼤于等于10的情况,
num1[j]=num1[j]-10;//如果有,则满⼗进⼀
}
}
if(num1[len_max])//判断是否最⾼位有满⼗进⼀的情况,如果有则显⽰结果,没有则不显⽰
{//因为之前已经把num1中的所有元素全部清成0了,所以如果那两个数相加的最⾼位没有满⼗进⼀的话,            printf("%d",num1[len_max]);//num1[len_max]这⼀位肯定是0,0在C语⾔中代表假,也就不会执⾏        } //if判断体中的代码了
for(j=len_max-1;j>=0;j--)//接着再逐位打印出来就⾏了
{
printf("%d",num1[j]);
}
printf("\n");
}
}
⽅法⼆:使⽤两个字符串数组、两个整型数组
#include<stdio.h>
#include<string.h>
int main()
{
int num1[1006],num2[1006],len1,len2,lenmax,i,j;
char str1[1006],str2[1006];
while(1)
{
scanf("%s %s",&str1,&str2);
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));//先清零
len1=strlen(str1);
len2=strlen(str2);
lenmax=len1>=len2?len1:len2;
for(i=len1-1,j=0;i>=0;i--,j++)
{
num1[j]=str1[i]-'0';//将字符串反转并且转换为数字保存在整型数组中        }
for(i=len2-1,j=0;i>=0;i--,j++)
{
num2[j]=str2[i]-'0';//将字符串反转并且转换为数字保存在整型数组中        }
for(i=0;i<lenmax;i++)
{
num1[i]=num1[i]+num2[i];//相加
if(num1[i]>=10)
{
num1[i]=num1[i]-10;//满⼗进⼀
num1[i+1]+=1;
}
}
if(num1[lenmax])//判断数字中最⼤的那个数字的最⾼位是否产⽣进位        {
printf("%d",num1[lenmax]);
}
for(i=lenmax-1;i>=0;i--)
{
printf("%d",num1[i]);
}
putchar(10);//打印换⾏,换⾏的ASCII编码为10
}
}
例题⼀:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。