题目整理:大整数加法

题目整理:大整数加法

1.题面

题目来源计蒜客T1098
求两个不超过 200 200 200位的非负整数的和。
输入格式
有两行,每行是一个不超过 200 200 200位的非负整数,可能有多余的前导 0 0 0
输出格式
一行,即相加后的结果。结果里不能有多余的前导 0 0 0,即如果结果为 342 342 342,那么就不能输出为 0342 0342 0342
输出时每行末尾的多余空格,不影响答案正确性。
样例输入

22222222222222222222222
33333333333333333333333

样例输出

55555555555555555555555

2.分析

(以下是本人的分析及代码,不是最优的代码)
(1)从控制台获取输入的数字,使用cin.getline()方法

char* snum1 = new char[300];		//存放第一行输入的数
char* snum2 = new char[300];		//存放第二行输入的数
cin.getline(snum1, 300);
cin.getline(snum2, 300);

(2)将获取的字符串转为int类型数组

  • 获取输入数字的位数
    len1存放第一个输入数字的位数,len2存放第二个输入数字的位数。
    (以第一个输入的数字为例,第二个输入的数字类似。)
int len1 = 0;				//存放第一个输入数字的位数
char* p = snum1;
while (*p != '\0')
{
	len1++;
	p++;
}
  • 转换为int类型数组
    该数组的特点是:输入数字的高位在数组中的下标也为高位,输入数字的低位在数组中的下标也为低位。例:输入数字为12345,则转换为的整型数组为{5, 4, 3, 2, 1}
    num1存放第一个输入数字,num2存放第二个输入数字,均为整型指针int*
    (以第一个输入的数字为例,第二个输入的数字类似。)
int* num1 = new int[len1];			//存放第一个输入的数字
for (int i = 0; i < len1; i++)
{
	switch (snum1[i])
	{
	case '0':
		num1[len1 - 1 - i] = 0;
		break;
	case '1':
		num1[len1 - 1 - i] = 1;
		break;
	case '2':
		num1[len1 - 1 - i] = 2;
		break;
	case '3':
		num1[len1 - 1 - i] = 3;
		break;
	case '4':
		num1[len1 - 1 - i] = 4;
		break;
	case '5':
		num1[len1 - 1 - i] = 5;
		break;
	case '6':
		num1[len1 - 1 - i] = 6;
		break;
	case '7':
		num1[len1 - 1 - i] = 7;
		break;
	case '8':
		num1[len1 - 1 - i] = 8;
		break;
	case '9':
		num1[len1 - 1 - i] = 9;
		break;
	default:
		break;
	}
}

(3)进行加法运算
由于两个整数相加,其和的位数最多为max{len1, len2} + 1
len = max{len1, len2}num存放两个整数相加的和。

int len = len1 > len2 ? len1 : len2;
int* num = new int[len + 1];

c表示低位进位,则num1[i] + num2[i] + c的个位作为num[i]的值,十位作为第i + 1位的低位进位。

int c = 0;
for (int i = 0; i < len; i++)
{
	if (i < len1 && i < len2)
	{
		int s = c + num1[i] + num2[i];
		num[i] = s % 10;
		c = s / 10;
	}
	else
	{
		if (len == len1)
		{
			int s = c + num1[i];
			num[i] = s % 10;
			c = s / 10;
		}
		else
		{
			int s = c + num2[i];
			num[i] = s % 10;
			c = s / 10;
		}
	}
}
num[len] = c;

这样,两个整数相加的和就存放在num数组中了。
(4)去除前导 0 0 0
num中存放的结果可能存在前导 0 0 0,需要去除。

int* q = num + len;
while (*q == 0 && q != num)
{
	q--;
}

此时,指针q指向的是结果中的最高非零位。对于num全为0的情况也适用,即通过条件q != num来判断。
最后就可以打印出结果了。

while (q != num)
{
	cout << *q;
	q--;
}
cout << *num;

(5)删除申请的动态内存

3.代码

整体代码如下:

#include <iostream>

using namespace std;

int main()
{
	char* snum1 = new char[300];
	char* snum2 = new char[300];
	cin.getline(snum1, 300);
	cin.getline(snum2, 300);
	int len1 = 0;
	int len2 = 0;
	char* p = snum1;
	while (*p != '\0')
	{
		len1++;
		p++;
	}
	p = snum2;
	while (*p != '\0')
	{
		len2++;
		p++;
	}
	p = NULL;
	int* num1 = new int[len1];
	int* num2 = new int[len2];
	for (int i = 0; i < len1; i++)
	{
		switch (snum1[i])
		{
		case '0':
			num1[len1 - 1 - i] = 0;
			break;
		case '1':
			num1[len1 - 1 - i] = 1;
			break;
		case '2':
			num1[len1 - 1 - i] = 2;
			break;
		case '3':
			num1[len1 - 1 - i] = 3;
			break;
		case '4':
			num1[len1 - 1 - i] = 4;
			break;
		case '5':
			num1[len1 - 1 - i] = 5;
			break;
		case '6':
			num1[len1 - 1 - i] = 6;
			break;
		case '7':
			num1[len1 - 1 - i] = 7;
			break;
		case '8':
			num1[len1 - 1 - i] = 8;
			break;
		case '9':
			num1[len1 - 1 - i] = 9;
			break;
		default:
			break;
		}
	}
	for (int i = 0; i < len2; i++)
	{
		switch (snum2[i])
		{
		case '0':
			num2[len2 - 1 - i] = 0;
			break;
		case '1':
			num2[len2 - 1 - i] = 1;
			break;
		case '2':
			num2[len2 - 1 - i] = 2;
			break;
		case '3':
			num2[len2 - 1 - i] = 3;
			break;
		case '4':
			num2[len2 - 1 - i] = 4;
			break;
		case '5':
			num2[len2 - 1 - i] = 5;
			break;
		case '6':
			num2[len2 - 1 - i] = 6;
			break;
		case '7':
			num2[len2 - 1 - i] = 7;
			break;
		case '8':
			num2[len2 - 1 - i] = 8;
			break;
		case '9':
			num2[len2 - 1 - i] = 9;
			break;
		default:
			break;
		}
	}
	int len = (len1 > len2 ? len1 : len2);
	int* num = new int[len + 1];
	int c = 0;
	for (int i = 0; i < len; i++)
	{
		if (i < len1 && i < len2)
		{
			int s = c + num1[i] + num2[i];
			num[i] = s % 10;
			c = s / 10;
		}
		else
		{
			if (len == len1)
			{
                int s = c + num1[i];
				num[i] = s % 10;
                c = s / 10;
			}
			else
			{
                int s = c + num2[i];
				num[i] = s % 10;
                c = s / 10;
			}
		}
	}
	num[len] = c;
	int* q = num + len;
	while (*q == 0 && q != num)
	{
		q--;
	}
	while (q != num)
	{
		cout << *q;
		q--;
	}
	cout << *num;
	delete[] snum1, snum2, num1, num2, num;
	snum1 = snum2 = NULL;
	num1 = num2 = num = q = NULL;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值