问题描述
求两个不超过 200 位的非负整数的和。
输入数据
有两行,每行是一个不超过 200 位的非负整数,没有多余的前导 0。
输出要求
一行,即相加后的结果。结果里不能有多余的前导 0,即如果结果是 342,那么就不能
输出为 0342。
输入样例
22222222222222222222
33333333333333333333
输出样例
Output Sample:
55555555555555555555
解题思路
C/C++中的 int 类型能表示的范围是[?231,?231–1]。
unsigned 类型能表示的范围是 [0,232?1]。所以,int 和 unsigned 类型变量,都不能保存超过 10 位的整数。( 10x<=232?1,x<=9.63)。参与运算的数如果大于10位数,基本数据类型已经无法表示。基本思想是:用数组模拟大整数,一个数组元素,放一位整数。不过一个数组元素存一位,空间上有点浪费,那么节省空间,可以一个数组存多位,比如说4位,注意的是进位的时候,这个时候的进位不再是10,而是10000。
代码实现
基本方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 200
int x[MAX_LEN + 20], y[MAX_LEN + 20], z[MAX_LEN + 20];
char a[MAX_LEN + 20], b[MAX_LEN + 20];
void char_to_int(const char s[ ], int x[ ])
{
int i = 0;
int len = strlen(s);
memset(x,0,MAX_LEN + 20);
int j = 0;
for(i = len - 1; i >= 0; i--)
{
x[j++] = s[i] - ‘0‘;
}
}
void big_int_add(const int x[], const int y[], int z[])
{
int i = 0;
memset(z,0,MAX_LEN + 20);
for(i = 0; i < MAX_LEN; i++)
{
z[i] += x[i] + y[i];
if(z[i] >=10)
{
z[i] = z[i] - 10;
z[i+1] ++;
}
}
}
void big_int_print(const int z[])
{
bool flag = 0;
int i = 0;
for(i = MAX_LEN; i >=0; i--)
{
if(flag)
printf("%d",z[i]);
else if(z[i])
{
printf("%d",z[i]);
flag = 1;
}
}
if(!flag)
printf("0");
printf("\n");
}
int main( )
{
scanf("%s",a);
scanf("%s",b);
char_to_int(a,x);
char_to_int(b,y);
big_int_add(x,y,z);
big_int_print(z);
return 0;
}
方法二
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define Radix_Len 4
#define Carry_num 10000
#define MAX_LEN (200 / Radix_Len + 1)
int x[MAX_LEN], y[MAX_LEN], z[MAX_LEN + 1];
char a[MAX_LEN ], b[MAX_LEN ];
void char_to_int(const char s[ ], int x[])
{
int i = 0;
int len = strlen(s);
memset(x,0,MAX_LEN);
int j = 0;
for(i = len; i > 0; i -= Radix_Len)
{
int tmp , k ;
tmp = 0;
const int low = i - Radix_Len > 0 ? i - Radix_Len : 0;
for(k = low; k < i; k++)
tmp = tmp * 10 + ( s[k] - ‘0‘);
x[j++] = tmp;
}
}
void big_int_add(const int x[], const int y[], int z[])
{
int i = 0;
memset(z,0,MAX_LEN);
for(i = 0; i < MAX_LEN; i++)
{
z[i] += x[i] + y[i];
if(z[i] >=Carry_num)
{
z[i] = z[i] - Carry_num;
z[i+1] ++;
}
}
}
void big_int_print(const int z[])
{
bool flag = 0;
int i = 0;
for(i = MAX_LEN; i >=0; i--)
{
if(flag)
printf("%d",z[i]);
else if(z[i])
{
printf("%d",z[i]);
flag = 1;
}
}
if(!flag)
printf("0");
printf("\n");
}
int main( )
{
scanf("%s",a);
scanf("%s",b);
char_to_int(a,x);
char_to_int(b,y);
big_int_add(x,y,z);
big_int_print(z);
return 0;
}
题目来自 OpenJudge 百练 http://bailian.openjudge.cn/practice/2981/
大整数减法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 200
int x[MAX_LEN + 20], y[MAX_LEN + 20], z[MAX_LEN + 20];
char a[MAX_LEN + 20], b[MAX_LEN + 20];
void char_to_int(const char s[ ], int x[ ])
{
int i = 0;
int len = strlen(s);
memset(x,0,MAX_LEN + 20);
int j = 0;
for(i = len - 1; i >= 0; i--)
{
x[j++] = s[i] - ‘0‘;
}
}
void big_int_add(const int x[], const int y[], int z[], int max_len)
{
int i = 0;
memset(z,0,MAX_LEN + 20);
int exchange = 0;
printf("%d %d\n",x[max_len - 1],y[max_len - 1]);
if(x[max_len - 1 ] < y[max_len - 1])
{
exchange = 1;
printf("-");
}
for(i = 0; i < MAX_LEN; i++)
{
if(exchange)
{
z[i] += y[i] - x[i];
}
else
{
z[i] += x[i] - y[i];
}
if(z[i] < 0)
{
z[i] = z[i] + 10;
z[i+1] --;
}
}
}
void big_int_print(const int z[])
{
bool flag = 0;
int i = 0;
for(i = MAX_LEN; i >=0; i--)
{
if(flag)
printf("%d",z[i]);
else if(z[i])
{
printf("%d",z[i]);
flag = 1;
}
}
if(!flag)
printf("0");
printf("\n");
}
int main( )
{
scanf("%s",a);
scanf("%s",b);
int max_len = 0;
int len1 = strlen(a);
int len2 = strlen(b);
max_len = len1 > len2 ? len1: len2;
char_to_int(a,x);
char_to_int(b,y);
big_int_add(x,y,z,max_len);
big_int_print(z);
return 0;
}
时间: 2024-10-03 22:25:05