大数问题,其实就是模拟运算,因为系统自带的int、long、bouble(double虽然可以表示很大的数,但那是使用的科学记数法,保存的数值的精度是有限的,最大精度只有十几位,后面的数字就保存不了了,会全变成0)这些类型均无法容纳百位乃至千位的大数字,从而手动模拟的运算过程,我们一般使用字符串来表示这样的超大数字。
测试数据:
/*
987654321987654321 987654321987654321
1975308643975308642
9999999999999999999 9
100000000000000000008
*/
基本上这两组测试数据过了就没啥问题了。
方法一:使用三个字符串【两个用于存储输入的待计算的大整数,一个用于过程计算中的临时存储】+一个整型数组【为了进位方便而设置的数组】
#include
#include
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就不变了,
我们只需要把数字位数最短的那个数字的位数补成和数字位数最长的那个数字的位数一样就行了
12 和998,我们知道结果是1010
对于12说,str1[0]=1,str1[1]=2
对于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
printf("str1[%d]=%c\n",i,str1[i]);
}
putchar(10);//打印换行,换行的ASCII代码是10
for(i=0;i
printf("str2[%d]=%c\n",i,str2[i]);
}*/
if(len1>=len2)
{
result=1;//用于观测哪个数字位数比较长
len_max=len1;
for(i=len2,j=0;i
str3[j]='0';
}
for(i=0;i
str3[j]=str2[i];
}
for(i=0;i
str2[i]=str3[i];
}
}
else
{
result=0;
len_max=len2;
for(i=len1,j=0;i
str3[j]='0';
}
for(i=0;i
str3[j]=str1[i];
}
for(i=0;i
str1[i]=str3[i];
}
}
len_max=len1>=len2?len1:len2;
for(i=len_max-1,j=0;i>=0;i--,j++)
{
num1[j]=str1[i]-'0'+str2[i]-'0';//把字符数组中的元素从个位到最高位依次计算
}
for(j=0;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
#include
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
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
}
}
例题一:1154: A + B Problem (X)【附大整数相加详解教程】
http://blog.csdn.net/coco56/article/details/79143475