大数是算法语言中的数据类型无法表示的数,其位数超过最大数据类型所能表示的范围,所以,在处理大数问题时首先要考虑的是怎样存储大数,然后是在这种存储方式下其处理的实现方法。
一般情况下大数的存储是采用字符数组来存储,即将大数当作一个字符串来存储,而对其处理是按其处理规则在数组中模拟实现。
一 大数加法。
思路很常规。先用字符数组录入大数,(这个时候高位存在数组下标小的位置。 如:最高位在arr[0]处。 ---输入方式原因)
然后再从高往低反向存入整数数组中。(使得低位在数组下标小的位置,符合常规。)
然后在进行计算,考虑进位情况。
加法比较简单,就不多说什么了。 直接上代码。
#include <stdio.h>
#include <string.h>
#define MAXLEN 1000
int main()
{
char a1[MAXLEN];
char a2[MAXLEN];
static int v1[MAXLEN];
static int v2[MAXLEN];
static int v3[MAXLEN];
int i,j,n,L,z;
scanf("%d",&n); //读入计算的组数
for (j=0;j<n;j++)
{
scanf("%s%s",a1,a2); //读入每组计算的2个大数
L=strlen(a1);
for (i=0;i<L;i++)
v1[i]=a1[L-1-i]-'0'; //大数a1反向
L=strlen(a2);
for (i=0;i<L;i++)
v2[i]=a2[L-1-i]-'0'; //大数a2反向
for (i=0;i<MAXLEN;i++)
v3[i]=v1[i]+v2[i]; //a1.a2各位直接相加,先不考虑进位
for (i=0;i<MAXLEN;i++)
{
if (v3[i]>=10)
{
v3[i+1]+=v3[i]/10; //对每位进行进位处理
v3[i]=v3[i]%10;
}
}
printf("Case %d:\n", j+1);
printf("%s + %s = ", a1, a2);
z=0;
for (i=MAXLEN-1;i>=0;i--) //打印
{
if (z==0)
{
if (v3[i]!=0)
{
printf("%d",v3[i]);
z=1;
}
}
else
{
printf("%d",v3[i]);
}
}
if (z==0) printf("0");
printf("\n");
}
return 0;
}
其实,上述代码还能进一步简化,合并操作步骤。
可以将大数的颠倒过程和求和运算过程合并,颠倒的过程是逐位移动到整数数组的过程,在移位的过程中,同时实现运算,但此时依旧先不考虑进位,所有各位的进位都在计算完成后统一处理。
#include <stdio.h>
#include <string.h>
int main()
{
char s[202]; // 假设大数不超过200位。
int sum[201];
int i, j, d, len, maxlen=0;
for (i=0;i<201;i++) //对各位和进行初始化
{
sum[i] = 0;
}
for (i=0;i<2;i++) // 读入两个大数
{
scanf("%s", s);
len = strlen(s);
if (len>maxlen)
maxlen = len;
for (j=len-1;j>=0;j--)
sum[len-1-j] += s[j] - '0'; //颠倒求和,存入结果数组sum中
}
for (i=0,d=0;i<maxlen;i++) //从低位开始处理结果中的进位
{
sum[i] += d;
d = sum[i] / 10;
sum[i] %= 10;
}
if (d>0)
sum[maxlen++] += d; //如果最后一个有进位,再往前挪一位
for (i=maxlen-1;i>=0;i--)
s[maxlen-1-i] = sum[i] + '0'; //结果以字符串方式保存
s[maxlen] = '\0';
printf("%s\n",s); //输出结果
return 0;
}
加法算法固然简单,也算大数的入门吧。也是有必要提一提的。