超大整数相加
输入
第一个数字M代表接下来有几组数据;
接下来每一组数据包含两个数据,数字很大哦;
确保没有前缀0,数据很大;
输出
输出计算后的结果,每个结果占一行;
样例输入
3
123 456
1234567890987654321 9876543210123456789
11111111111111111111111111111 111111111111111111111111111111
样例输出
579
11111111101111111110
122222222222222222222222222222
*/
/* 解决这个问题需要处理的小问题:
1.如何存储很长的数字(类型的变量存不了几十位长的整数!)
2.如何将存储的数据以合适的方法取出来,进行计算
/
/ 下面用的方法是啰嗦的,但是明确了:往字符数组里填充某个整数,该整数会被视为某个字符的ascii码值.
而往整形数组里填充整数,那促进去的就是整数本省(吗?)
探究了如何从整数存到字符数组,如何从字符数组提取出一位(叫数码吗?)整数(0~9范围的)(相差48/‘0’)
对与0有关的数组的初始化往往会漏带掉导致随机值的莫名其妙
同一数组使用strcpy是十分不建议的. */
#include <stdio.h> #include <string.h> // 返回字符串?/指向字符串的指针? char strlonger(); int main(){ //printf("test_4\n"); int n; while(scanf("%d",&n) != EOF) { for(int i = 0;i<n;i++) { char recieve_big_number_1[10000];//数组不够大可能无法输出结果/ char recieve_big_number_2[10000]; char sum_up[10000]; scanf("%s%s",recieve_big_number_1,recieve_big_number_2);/* 暂且 将输入大数视为字符串 存入字符数组. */ int dif;/*差值difference */ char *big; char *small;//char (*small)[100];small = recievi_big_number_1,到底哪种形式可行呢? int len_small; int len_big; int up = 0; /* 判断那个数大 ,使用abs的话会简洁些*/ if( ( dif = strlen(recieve_big_number_1) - strlen(recieve_big_number_2) ) >= 0) { big = recieve_big_number_1; len_big = strlen(big); small = recieve_big_number_2; len_small = strlen(small); } else { big = recieve_big_number_2; len_big = strlen(big); small = recieve_big_number_1; len_small = strlen(small); dif = -dif; } strcpy(&sum_up[1],big);/* 试图空出sum_up[0]这个可能的最高位. (该操作确实可行) */ /* 当然,这样sum_up[0]的值是随机的,你以选择初始化,当然这题不必须,因为输出的为可能1.从[1]开始输出;2.[0]会被进位值覆盖(为1) */ /* 位置对齐(其实这件事并不必要 ,当然,它对于连锁进位还是提供了方便): 但还可以调整填入sum_up的顺序来(高位往后填充,再逆序从高到低输出.)这就无需对齐 事实上,逆(反)序填充,正序输出的手段可以减少很多的不必要的工作量(输出方式是很灵活的), 考试的话前者的定位更合适,平时我们正序排列还正序输出只是为了试验某些知识点,检验思维漏洞(这还未必能办到,就不要死磕)*/ /* 版本一有巨大缺陷 */ // if(dif > 0) // { // int j = 0; // for(int i = 0;i<len_small;i++) // { // // 调试时,若看指针的话,只能看到首地址对应元素的变化,更应该观察的是指针所指的源数组的被间接改变的结果 // /*考虑dif== 0, */ // small[i+dif] = small[i]; // //small[i] = '0';这么些的话,前面一串都被赋值为0.考虑另用一个互不干扰的变量 // if(j<dif) // small[j++] ='0';//'0'就是48啦.(int) // } // small[len_small] = '0'; //这句话有待商榷: // } /* 版本2 */ // // strcpy(small[len_big - len_small],small);这里是为什么?处理较长的的输入是就会报错segmentation fault /* 在同一个字符串中使用strcpy有哪些风险? */ for(int i = 0;i<len_small;i++) { /* 如同交换两个变量的值,为了避免重叠的问题,还应开一个buf // 或者考虑从后面的字符开始挪,可以避免重叠造成覆盖,数据丢失*/ /* 值得一提的是,类似的操作再不同的顺序安排下可能产生巨大的不同 */ small[len_small - 1 - i+dif] = small[len_small -1 -i] ; } for(int i = 0;i<len_big -len_small;i++)//可以考虑使用字符串函数. { small[i] = '0'; } /* 打个补丁 */ small[len_big] = '\0'; /* 对齐后刷新len_small */ len_small = strlen(small); /* 将字符转化为数字 */ /* int big_last; big_last = (int)big[len_big-1] - 48; */ //test将会是存入的数字字符的ASCII值,然而, //由于ASCII值具有良好的递增规律,-48就可以转换为输入的数字大小了 //printf("%d",test); /* 小学的按位加法(及进位) */ for(int i = 0;i<len_big /* && i<len_small */;i++)/* i 类似(前移)改变量 */ { /* 以下可以得到迭代 */ int signal_add_i = 0; /* signal_add_i本身不依赖于对齐 */ signal_add_i = (int)big[len_big-1 - i ] - 48 + (int)small[len_small-1 -i] - 48 + up ; up = 0;/* 加完进位,使得进位记录器up归零,否则up回不去了 */ /* 如果发生进位 */ if( signal_add_i >= 10) { up = 1; /* int fill_sum_up; fill_sum_up = (char)(signal_add_i / 10) + 48; sum_up[len_big - i ] = fill_sum_up; */ int fill_sum_up; fill_sum_up = (signal_add_i % 10) + '0'; sum_up[len_big - i ] = fill_sum_up; } /* 若不发生进位 */ else sum_up[len_big - i ] = signal_add_i + '0'; } // if(up == 1) /* 我竟然写成了赋值号 = */ { sum_up[0] = '1'; printf("%s\n",sum_up); //printf("\n out1 : %s\n",sum_up);//更清楚输出 } //if(up = 1) sum_up[len_big - len_small - 1] += 1; /* 打印的时候分个类(首位是否被进位) */ else printf("%s\n",&sum_up[1]); /* 非首地址,需& */ //printf("\n out2: %s\n",&sum_up[1]); } } return 0; }
版本_2:(简)
#include <stdio.h> #include <string.h> int main() { int n; /* 这块代码不可放在外部(测试多组数据时,有残留) char s1[100], s2[100]; 再开一对整形数组,存储接受的字符串所转化成的整形数据,即提取各位上的数码,便于运算.而且不会破坏输入数据 int num1[31], num2[31], len1, len2, i, j; */ while (scanf("%d",&n) != EOF) { for (int i = 0; i < n; i++) { char s1[10000], s2[10000];/*允许近万位数相加*/ //再开一对整形数组,存储接受的字符串所转化成的整形数据,即提取各位上的数码,便于运算.而且不会破坏输入数据 int num1[10000] = { 0 },/*每一位都初始化为0.*/ num2[10000] = { 0 }, len1, len2, i, j; scanf("%s%s", s1, s2);/*%s来读取输入*/ len1 = strlen(s1); len2 = strlen(s2); /* 两个控制变量,使得字符转数字的填充过程中,低位填在前,高位向后填,方便数位对齐相加*/ i = len1 - 1;/*从最低为起往高位(向前)*/ j = 0;/*从最高位往低位(向后)*/ for (; i >= 0; ) { num1[j] = s1[i] - 48; //从字符到整数的转换(0~9),并且填充到整形数组 j++; i--; } /*处理第二个操作数*/ for (i = len2 - 1, j = 0; i >= 0; i--) { num2[i] = s2[j] - 48; j++; } /* (len2 > len1 ? len2 : len1)的运算结果是len2和len1的较大值,十分紧凑 */ for (i = 0; i < (len2 > len1 ? len2 : len1); i++) { /* 将相加(第i位)的结果保存到num1[i]里 */ num1[i] += num2[i];/*相加结果<=9,直接保存(最理想)*/ /* 如果需进位(>9):可以表示位10+k (0<=k<=9) */ if (num1[i] > 9) {/*向高一位进位+1 */ num1[i + 1] ++; /* 迭代高一位的数码,让其+1 */ /*继续处理当前位:*/ num1[i] -= 10; /* 留下个位,放在当其位置 */ } } //for(本循环无法判断最高位;两个数相加,若数量级增大,则最高位必为1) /* 最高位的情况(是否进位,以及填充到适当的位置 还需单独判断下: */ /* 上头的i++在跳出for是已经移位都最高位(如果进位的话) */ /* 最低位放在num1数组的最前面,这样方便处理未知的最高位,届时逆序输出即可 (从后往前打印(高位-->低位)) */ /*如果进位*/ if (num1[i]) /* 最高位是否1(此时的num1[i]只为1/0 (1是低位进上去的;0则是之前memset()初始化的值,且没有进位)) */ { for (j = i; j >=0 ; j--) /* 或说:j >= 0 */ printf("%d", num1[j]); printf("\n"); } /*不进位: */ else { for (j = i - 1; j > -1; j--) printf("%d", num1[j]); printf("\n"); } } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2021-11-25 python@python@本地文档@帮助系统@pip@配置和换源