stm32 整数加法循环时间_【题解高精度】1168:大整数加法

c1ae09e9f9fde4ad4fe5996b8a716447.png 452b49eedc3432583243bf565ef06d9e.png1168:大整数加法 时间限制: 1000 ms    内存限制: 65536 KB

【题目描述】

求两个不超过200位的非负整数的和。

【输入】

有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。

【输出】

一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

【输入样例】

22222222222222222222

33333333333333333333

【输出样例】

55555555555555555555

说明:

主要考查高精度加法。

题目概述:

C++整型的最大值也不超过20位数字,而本题求两个不超过200位的加数相加之和。很明显,不能使用常规的方法直接求解。

题目提示《可能有多余的前导0》,说明输入的并不是整型数值,而是字符串。字符串中的每个字符其实就是char类型字符,而char类型其实也是一种整型,可以进行相加的操作。

所谓前导0,是在数字的最前面有1个及以上的0,例如数字123,但输入的时候可能是0123或000123。

所以,输入字符串,把字符串中的字符转换为整型一一相加,就能得出最终的结果。

思路分析:

如果有两个char数组a1和a2,输入的两个加数是:

7ca2bee11cab9889d324badc0912a8b5.png

那么有:

char a1 = "00123456789";

cahr a2 = "987654321";

很明显,一个加数有前导0。而且高位在左边,低位在右边。

转换为竖式,并把多余的前导0去掉:

31556bbed0b4365c35a690b14ab1c430.png

如上图所示,如果直接使用竖式加法,算出结果不难。但要考虑是在两个char数组的基础上相加,而且有无前导0,有多少个前导0,哪个数组有前导0。

char数组也是一个字符串,此时不妨把字符串反过来,变成:

a1 = "98765432100";

a2 = "123456789";

很明显,从左往右就是从低位到高位。如果不翻转,两个加数的个位可能不对齐。现在数字经过翻转后,不需要考虑个位是否对齐的问题,而且对于高位的前导0也无需考虑,因为char类型的字符串是以空字符'\0'结尾,只要遇到空字符,结束运算即可。

同时,还要考虑进位问题,例如15+16=31,5+6=11,要进位。因为个位数字相加时,不需要加上进位值,所以可以声明一个int类型变量z = 0作为进位值。从十位数字开始,加上进位值,如果相加大于9,也要进位。

如上图的例子,个位9+1=10,所以个位为0,进位变量为1。十位8+2=10,但要加上由个位进位的1,所以是11,而11>9,也要进位。

以上便是解题的主要思路,其实就是竖式加法,只不过现在是应用在编程中。其次,还要考虑细节问题。例如需不需要翻转字符串,是否删除前导0,是否把char数组转换为int数组等等。

解决本题的不止有一种方法,其核心还是运用竖式加法。为了让大家能学习更多的知识以及了解更多的技巧,本题解将把多个细节都一一列举,即处理翻转char数组,去除前导0,以char类型进行加法运算(即不转换为int数组)。

数据类型:输入的加数都是字符串类型,可选string或char数组。

重难点:

本题难度不大,注意有前导0的情况。

解决本题的关键是输入的加数以字符串的形式输入,相加时注意进位。其他细节可以灵活变通,例如是否需要翻转字符串,对前导0如何处理,选择string还是char数组等等。

求解过程:

声明2个char类型数组a1[202] = {0}和a2[202] = {0},分别表示两个加数。

输入两个加数。

声明1个int类型数组a3[203] = {0},用于存储两个加数之和。

声明4个int类型变量t、x = 0、y = 0、z = 0,t用于交换数据,x用于记录第一个加数个位数字的下标,y用于记录第二个加数个位数字的下标,z用于存储进位值。

声明2个int类型变量n1和n2,n1用于获取数组a1的实际长度,n2用于获取数组a2的实际长度。使用库的strlen函数可获取char数组的实际长度(不包括空字符)。

循环获取第一个加数个位数字的下标,while(a1[x] && a1[x+1]),循环体中:

1.如果a1[x]等于字符'0',则x加1。

2.否则,退出循环。

循环获取第二个加数个位数字的下标,while(a2[y] && a2[y+1]),循环体中:

1.如果a2[y]等于字符'0',则y加1。

2.否则,退出循环。

上述两个循环可以获取前导0的长度,实际上也是个位数字的下标。

使用循环翻转字符数组a1和a2,使其个位数在前,翻转时,前导0不动,只翻转真实数字。

使用循环开始相加,并把运算的结果存储在数组a3中,把进位值存储在变量z中。

判断进位变量z是否为1,如果为1,表示继续进位,数组a3的实际长度也要加1。

循环输出最终的结果,即数组a3。

运行结果:

031e009eb0f532e3e002f0053db55ecb.gif

参考代码 - C++:

除此之外,还要考虑加数为0的情况。代码中的48其实是字符'0'的ASCII码,这是一个基础知识,必须要掌握。

代码中运用了一些小技巧,例如逗号表达式、在数组中运用自加运算符、条件运算符等,能体现C++的灵活性。作为初学者在理解上可能有点难度,不过对于初学算法的同学来说,何尝不是一个锻炼的机会。

#include 
#include 
using namespace std;
int main(){
    char a1[202] = {0}, a2[202] = {0};
    cin >> a1 >> a2;
    int a3[203] = {0}, t, x = 0, y = 0, z = 0;
    int n1 = strlen(a1), n2 = strlen(a2);
    while (a1[x] && a1[x + 1]) // 获取个位数字的下标
    {
        if (a1[x] == 48) x++;
        else break;
    }
    while (a2[y] && a2[y + 1])
    {
        if (a2[y] == 48) y++;
        else break;
    }
    // 把整数翻转过来,即个位数在前
    for (int i = x, k = 0, m = (n1 - x + 1) / 2 + x; i         t = a1[i], a1[i] = a1[n1 - 1 - k], a1[n1 - 1 - k++] = t;
    for (int j = y, k = 0, m = (n2 - y + 1) / 2 + y; j         t = a2[j], a2[j] = a2[n2 - 1 - k], a2[n2 - 1 - k++] = t;
    n1 -= x; // 减去前导0的数目,才是真实的长度
    n2 -= y;
    if (n1 // 获取最大整数的长度
    for (int k = 0; k // 开始相加求和
    {
        a3[k] = (a1[x] ? a1[x] - 48 : 0) + (a2[y] ? a2[y] - 48 : 0) + z;
        if (a3[k] >= 10) z = 1, a3[k] -= 10; // 判断相加后是否进位
        else z = 0;
    }
    if (z) a3[n1++]++; // 如果进位值不为0,说明最高位要进位
    for (int i = n1 - 1; i >= 0; i--) cout <    return 0;
}

28819d434cf2f549b4465d010f21f159.png

END

注:题目来源于网络,转载于《信息学奥赛一本通(C++版)在线评测系统》,点击下方的【阅读原文】即可打开该题的链接。

题解属于本微信公众号【大神编程】原创。

7aa72bfeaf538411ad862e20612cf68c.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值