当前位置: 首页 > news >正文

C++ 实现大数加法

一、问题描述

  • 大数的加法即两个非常大的数字进行相加,数字的大小超过了long long的表示范围(溢出)。由于数字可能非常大,不能直接转换为内置整型计算,必须逐位模拟竖式相加。
  • 例如,要求实现两个非负整数的加法(负数的话直接算完前面加个负号即可),输入的数值为a = 42312313432351231276453587647867123561273189378912673678和b = 239123128973127663451234523478634675781267814562345612837324,请输出它们的和。

二、算法思想(竖式相加)

  1. 从两数的最低位(字符串最后一个字符)开始逐位相加。
  2. 每一位的计算包括两个对应位的值以及来自低位的进位(carry)。
  3. 若相加结果 ≥ 10,则该位结果为 sum - 10,并向高位产生进位 1。
  4. 当两个字符串长度不同,较长数剩余的位要继续加上可能存在的进位。
  5. 最终若最高位仍有进位,则在结果最前面补上 1
  6. 将每位结果拼接回字符串并返回(注意去掉可能的前导零)。

三、示例代码解析(核心思想与实现)

在这里插入图片描述

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef long long ll;/*将按位存放的数组转为字符串,并忽略前导零参数 arr: 每个元素是 0~9 的位值(高位在前,低位在后),可能有前导 0返回值: 去除前导零后的数字字符串;如果全为 0 则返回空字符串(使用者可判定)
*/
std::string num_arr_to_string(std::vector<int> arr){std::string a("");bool begin = false; // 标记是否遇到第一个非零位for (int c: arr){if (c != 0){begin = true;}if (begin){a += std::to_string(c);}}return a;
}// 调试用:打印数组中的每个元素(空格分隔)
void show_arr(std::vector<int> arr){for (int c: arr){std::cout << c << " ";}std::cout << std::endl;
}// 检查一个字符串是否全为 0
bool is_zero_str(std::string a){for (char c: a){if (c != '0')return false;}return true;
}/*大数相加(把结果保存在字符串中)输入:a, b —— 表示两个非负整数的字符串(例如 "123", "9")输出:a + b 的结果(字符串形式)说明:- 作者用一个整型数组 arr 保存计算过程的每一位,最后再转成字符串返回- 注意:代码里把 arr 的长度设为 lens = max_len * max_len,这里长度远大于实际需要。这样做虽然“安全”但浪费空间。后面博客会指出更合理的做法:长度为 max_len + 1 即可。
*/
std::string big_num_add(std::string a, std::string b){if (is_zero_str(a) && is_zero_str(b)){return "0";}int max_len = std::max(a.length(), b.length());ll lens = max_len * max_len; // 原代码使用 max_len*max_len(过度分配)std::vector<int> arr(lens + 1, 0); // 存放每一位的结果(高位在前,低位在后),初始化为 0bool jin = false; // 进位标记(carry),true 表示上一位有进位 1int i = a.length() - 1; // 指向字符串 a 的最低位(从后向前遍历)int j = b.length() - 1; // 指向字符串 b 的最低位int idx = lens; // arr 的填充索引(从后向前填充)// 同时处理 a 和 b 都还有位的情况while (i >= 0 and j >= 0){int xi = a[i] - '0'; // 当前 a 的位(0-9)int xj = b[j] - '0'; // 当前 b 的位(0-9)int num = xi + xj + jin; // 当前位相加(含进位)if (num >= 10){jin = true;num -= 10; // 只保留当前位}else{jin = false;}arr[idx] = num; // 存入当前位i -= 1;j -= 1;idx -= 1;}// 如果 a 还有剩余位,继续处理(把进位加到剩余位上)if (i >= 0){while(i >= 0){int xi = a[i] - '0';int num = xi + jin;if (num >= 10){jin = true;num -= 10;arr[idx] = num;}else{jin = false;arr[idx] = num;}i -= 1;idx -= 1;}// 若遍历完仍然有进位,把 1 放到当前 idx 处(高位)if (jin) { arr[idx] = 1; }}// 如果 b 还有剩余位,继续处理(逻辑与上面对称)if (j >= 0){while(j >= 0){int xj = b[j] - '0';int num = xj + jin;if (num >= 10){jin = true;num -= 10;arr[idx] = num;}else{jin = false;arr[idx] = num;}j -= 1;idx -= 1;}if (jin) { arr[idx] = 1; }}if (jin) {arr[idx] = 1;} // 没有分支时的进位// show_arr(arr); // 可启用来查看数组计算状态(调试用)return num_arr_to_string(arr); // 把结果数组转换为字符串返回(去除前导零)
}int main(){std::string a, b;std::cin >> a >> b; // 从标准输入读取两个字符串(假设都是非负整数且无额外空格)std::string res = big_num_add(a, b);std::cout << res; return 0;
}
  • 存储结构:代码使用 std::vector<int> arr 来保存每一位的结果(高位在前,低位在后),最后通过 num_arr_to_string 去掉前导零并转换为字符串返回。
  • 进位处理:用布尔变量 jin 表示当前是否有进位(true 表示有 1 的进位)。在每一步相加后更新 jin
  • 数组大小:原代码中将 arr 的长度设为 max_len * max_len,这是一种“超保守”的做法——保证数组足够大,但会严重浪费空间。更合理的做法是把数组长度设为 max_len + 1,因为两个长度为 max_len 的数相加最多产生一个额外的最高位进位。
  • 返回值num_arr_to_string 会去掉前导零;若结果为零,当前实现会返回空字符串(这点可以改进为返回 "0",更符合直觉)。

四、代码逐行要点说明(关键处总结)

  • int i = a.length() - 1, j = b.length() - 1;:从两数的最低位开始处理。
  • int num = xi + xj + jin;:加上三个部分:a 的位、b 的位、进位。
  • num >= 10,设置 jin=truenum-=10,否则 jin=false
  • 遍历结束后,若仍有 jin,需在更高位写入 1
  • 最后调用 num_arr_to_string 去掉高位多余的 0 并得到字符串结果。

五、时间与空间复杂度

  • 时间复杂度:O(n),其中 n = max(len(a), len(b)),每个位最多被访问常数次。
  • 空间复杂度:原代码 O(L^2)(因为用了 max_len * max_len),但最合理的实现只需 O(n)(长度 n + 1 的数组或直接构造字符串存放结果)。

八、总结

大数运算是很多竞赛与工程场景常见的基础问题,掌握逐位相加、进位处理,以及如何在字符串/数组与结果字符串之间高效转换,是写出可靠代码的关键。

http://www.dtcms.com/a/570211.html

相关文章:

  • 图片展示网站青岛微网站制作
  • WebRTC 项目中捕获 FFmpeg 底层源码日志(av_log)的完整方案
  • 做建材上哪个网站比较好微信小程序申请场所码
  • 网站公司网站开发外网设计素材网站
  • 搭建hadoop集群
  • leetcode 3318 计算子数组的x-sum I
  • MAC-SQL:SQL-Llama 的具体训练流程
  • 国内python 做的网站网站建设教程照片
  • 家用电脑和宽带做网站做网站需要多长时间才能做好
  • 配置git/创建第一个智能相册保存快照
  • 网站建设与维护本科教材写文的免费软件
  • 网站开发需要多少行代码兰州吸引用户的网站设计
  • C# XML文件的读写V2.0
  • 怎么做可以把网站图片保存下来天猫网站左侧导航用js怎么做
  • 台州网站建设哪家公司好成品源码灬1688高清完整版
  • 东莞网站建设广东网站建设模版
  • 郑州做网站好网站建设 全网推广
  • asp.net网站开发 vs2017网站目录在哪
  • 接口自动化测试框架搭建详解
  • 成都网站建设爱特通dw软件下载
  • 台州椒江网站建设公司软件开发外包费用评估
  • springboot配置项目的url
  • 智慧车辆视频分析技术
  • 自己制作上传图片的网站怎么做网页设计教程博主
  • 错题笔记总结:PCI与PCIe:并行与串行
  • 做内部网站费用广东建的电商网站叫啥
  • 云南省城乡住房与建设厅网站物业公司网站模板
  • 深圳在建高铁站wordpress 漏洞
  • 学做网站的步骤ps如何做网站专题
  • 怎么看网站是什么语言做的后台阿里云做网站麻烦吗