[C/C++] -- 大数的加减法

大数加减法的问题主要产生于计算机基本数据类型的表示范围限制。通常情况下,计算机采用有限位数的数据类型(如int、long)来表示整数,这些数据类型的表示范围有限,无法表示超出范围的大整数。

例如超过了long类型的表示范围(通常为-9223372036854775808 到 9223372036854775807),就无法直接使用基本数据类型进行计算。这时候就需要使用特殊的方法来表示和处理这些大数。

在实际应用中,大数加减法常见于金融计算、科学计算、密码学等领域。例如,在金融领域中,需要处理非常大的金额或利率;在科学计算中,可能需要处理超过基本数据类型表示范围的测量数据或计算结果;在密码学中,需要处理大素数或大整数来进行加密、解密等操作。

  1. 大数表示方法:使用字符串或数组等数据结构来表示大数。每个位上的数字可以用字符 '0' 到 '9' 来表示,例如:"12345678901234567890"。

  2. 大数加法

    • 从两个大数的最低位开始逐位相加,将结果存储到一个新的字符串或数组中。
    • 需要考虑进位的情况,即当相加结果超过9时,需要将进位加到下一位的运算中。
    • 需要考虑两个大数长度不等的情况。
  3. 大数减法

    • 从两个大数的最低位开始逐位相减,将结果存储到一个新的字符串或数组中。
    • 需要考虑借位的情况,即当相减结果小于0时,需要向高位借位。
    • 需要考虑被减数小于减数的情况,可以在代码中进行判断并抛出异常或返回特定结果。
  4. 进位和借位处理:编写逻辑来处理加法中的进位和减法中的借位。

运算符重载函数声明为 BigInt 类的友元函数是为了在不暴露私有成员的情况下,让它们能够有效地操作 BigInt 对象。

class BigInt 
{
public:BigInt(string str) : strDigit(str){ }
private:string strDigit;//使用字符串存储大整数//都是全局函数声明为友元friend ostream& operator<<(ostream& out, const BigInt& src);friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);};

 重载输出流插入运算符 <<,允许使用 << 将 BigInt 对象输出到输出流中。ostream& out 是一个输出流对象的引用,它表示要输出的目标流,而 const BigInt& src 是一个常量引用,表示要输出的 BigInt 对象。

ostream& operator<<(ostream& out, const BigInt& src)
{out << src.strDigit;return out;
}

 完整代码:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;class BigInt 
{
public:BigInt(string str) : strDigit(str){ }
private:string strDigit;//使用字符串存储大整数//都是全局函数声明为友元friend ostream& operator<<(ostream& out, const BigInt& src);friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);};
//打印函数
ostream& operator<<(ostream& out, const BigInt& src)
{out << src.strDigit;return out;
}//大数加法
BigInt operator+(const BigInt& lhs, const BigInt& rhs) {//从后往前遍历字符串lhs,和rhs,用flag来标记是否需要进位,结果存在result数组中(反向的)string result;bool flag = false;int i = lhs.strDigit.length() - 1;//string的length和size没有区别,length是沿用C语言习惯,早先只有lengthint j = rhs.strDigit.length() - 1;for (; i >= 0 && j >= 0; --i, --j) //i 和 j其中一个会被减到负数然后退出for循环{int ret = lhs.strDigit[i] - '0' + rhs.strDigit[j] - '0';//单个位加减时需要减'0'转成整型,每次都重新定义一个新的retif (flag){ret += 1;//flag为true说明此位因为上一位进位而需要多加一个1flag = false;//再将其重新置为false}//两个if不能互换,否则不是下一位进1if (ret >= 10){ret %= 10;flag = true;}result.push_back(ret + '0');}//如果遍历完,i还有剩下,第一个字符串没完if (i >= 0)//注意要取等,因为更短的那个字符串的下标是被减到-1,而不是0,0依然说明还剩余1位{while (i >= 0){int ret = lhs.strDigit[i] - '0';if (flag)                 //前面加过来可能还有进位,然后当前可能为9,加了1之后又 = 10,又得进位,所以直接复制前面的代码{ret += 1;flag = false;}if (ret >= 10){ret %= 10;flag = true;}result.push_back(ret + '0');i--;	}}//第二个字符串没完else if (j >= 0){while (j >= 0){int ret = lhs.strDigit[j] - '0';if (flag)                 //前面加过来可能还有进位,然后当前可能为9,加了1之后又 = 10,又得进位,所以直接复制前面的代码{ret += 1;flag = false;}if (ret >= 10){ret %= 10;flag = true;}result.push_back(ret + '0');j--;}}//最高位可能也进位if (flag) {result.push_back('1');}reverse(result.begin(), result.end());return result;//result是string类,而不是BigInt,因为隐式转换,p263//因为编译器看到该类的构造函数只接受一个实参(而且是string类的),所以可以触发隐式转换机制,定义string result时编译器也会构建一个BigInt类的临时对象,并把result赋值给他//函数里的return本来就是返回临时对象,这个时候就返回的就是那个BigInt类的临时对象//当然,参考书上的例子,即使后面函数用string类的result,编译器实际传入的也是BigInt的临时对象//如某成员函数定义为func(BigInt& a){...}; 调用时传入string类 func(result);也是合法的
}//大数减法
BigInt operator-(const BigInt& lhs, const BigInt& rhs) {//让大的减小的,如果lhs比rhs小,则让rhs - lhs,然后最后添加负号string result;bool flag = false;bool minor = false;//标记lhs是否和rhs互换了string maxStr = lhs.strDigit;string minStr = rhs.strDigit;if (maxStr.length() < minStr.length()){//互换,让maxStr一直是最长的maxStr = rhs.strDigit;minStr = lhs.strDigit;minor = true;}//长度一样也得比较else if (maxStr.length() == minStr.length()){if (maxStr < minStr){maxStr = rhs.strDigit;//让maxStr是最大的minStr = lhs.strDigit;minor = true;}else if (maxStr == minStr){return string("0");}}int i = maxStr.length() - 1;//i肯定大于等于j,所以后面j会先完int j = minStr.length() - 1;for (; i >= 0 && j >= 0; --i, --j) {int ret = maxStr[i]  - minStr[j];//减法的话,char类型相减就是int型了,不用+‘0’再相减/*if (ret >= 0){result.push_back(ret + '0');} 一定要先看标记,因为被借位的话,当前ret需要减1*/if (flag){ret -= 1;flag = false;}//当前位有可能因为被借位了而减,小于0,所以紧接着判断是否为负if (ret < 0){ret += 10;// 如2 - 6,应该是12 - 6,所以为 2 - 6 + 10 = 6flag = true;}result.push_back(ret + '0');}//肯定是j先完,所以不用再像加法那样判断,而是直接把i多余的处理完while (i >= 0) {int ret = maxStr[i] - '0';if (flag) {ret -= 1;flag = false;}//同样的,ret可能原本是0,被借位了又为-1了if (ret < 0) {ret += 10;flag = true;}result.push_back(ret + '0');i--;}//翻转前先看看末尾有没有0,如1000,否则反转后就是0001while(result.back() == '0'){result.pop_back();}if (minor) {result.push_back('-');}reverse(result.begin(), result.end());return result;
}int main()
{string s1;string A;string s2;getline(cin, s1);getline(cin, A);//把加减号定义为char会报错,getline第二个参数只能是string类型getline(cin, s2);BigInt int1(s1);BigInt int2(s2);if (A == "+") {cout << int1 + int2 << endl;}if (A == "-") {cout << int1 - int2 << endl;}return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/835369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaScript】内置对象 - 数组对象 ⑤ ( 数组转字符串 | toString 方法 | join 方法 )

文章目录 一、数组转字符串1、数组转字符串 ( 逗号分割 ) - toString()2、数组转字符串 ( 自定义分割符 ) - join() Array 数组对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array 一、数组转字符串 1、数组转字符串 ( 逗…

指针(脑图梳理)

今天让我们来梳理一下指针都有哪些概念吧 这个脑图是整理的一些指针相关知识的概念&#xff0c;希望对大家有帮助

Web前端开发 小实训(三) 商品秒杀小练习

学生能够在本次实训中完成商品秒杀页面的基本逻辑 任务要求 能够实现某一个商品的秒杀&#xff0c;在倒计时结束后不再进行秒杀。 操作步骤 1、打开预设好的页面 <html><head><meta charset"utf-8"><title>秒杀</title><link …

python中如何把list变成字符串

python中如何把list变成字符串&#xff1f;方法如下&#xff1a; python中list可以直接转字符串&#xff0c;例如&#xff1a; data ["hello", "world"] print(data1:,str(data)) 得到结果&#xff1a; (data1:, "[hello, world]") 这里将整个…

视频号小店究竟有什么秘密,值得商家疯狂入驻,商家必看!

大家好&#xff0c;我是电商花花。 我们都知道视频号和抖音本身都是一个短视频平台&#xff0c;但是随着直播电商的发展&#xff0c;背后的流量推动逐步显露出强大的红利市场和变现机会。 视频号小店流量大和赚钱之外&#xff0c;还非常适合普通人创业。 这也使得越来越多的…

easypoi动态表头导出数据

需求&#xff1a;动态导出某年某月用户和用户评分数据信息&#xff0c;表头(序号、姓名、用户姓名)&#xff0c;数据(所有用户对应的评分以及平均分)&#xff1b; 分析&#xff1a;1、表头除过序号、姓名&#xff0c;用户姓名要动态生成&#xff1b; 2、用户评分信息要和表头中…

【赠书活动第4期】《Rust编程与项目实战》

赠书活动 《Rust编程与项目实战》免费赠书 3 本&#xff0c; 收到赠书之后&#xff0c;写一篇 本书某一节内容 的学习博客文章。 可在本帖评论中表示参加&#xff0c;即可获得赠书&#xff0c;先到先得。学习心得博客链接&#xff0c;后面有空发上来。 赠书截止日期为送出3…

无人播剧直播收益在哪里!快手无人播剧新秘籍:版权无忧,日入四位数攻略

无人播剧顾名思义就是通过短视频平台直播不需要真人出镜受众群体通过网络短视频平台看到的经典影视剧集可以实现24小时不停断的播放利用多种途径变现的一种直播形式 1、操作简单、不露脸、不出镜2、手机、电脑都可以操作3、可以矩阵操作4、0粉丝、0作品、0保证金就可以开播5、…

2010-2030年GHS-POP数据集下载

扫描文末二维码&#xff0c;关注微信公众号&#xff1a;ThsPool 后台回复 g008&#xff0c;领取 2010-2030年100m分辨率GHS-POP 数据集 &#x1f4ca; GHS Population Grid (R2023)&#xff1a;全球人口分布的精准视图与深度应用 &#x1f310; 在全球化和快速城市化的今天&am…

[嵌入式系统-73]:RT-Thread-快速上手:如何选择RT Thread的版本?

目录 如何选择合适的 RT-Thread 版本进行开发&#xff1f; RT-Thread 分支与版本介绍 如何选择 发布版本&#xff08;GitHub releases&#xff09; 开发分支&#xff08;GitHub master 主分支&#xff09; 长期支持分支&#xff08;GitHub lts-v3.1.x 分支&#xff09; …

10.轮转数组

文章目录 题目简介题目解答解法一&#xff1a;使用额外的数组代码&#xff1a;复杂度分析&#xff1a; 解法二&#xff1a;数组反转代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 轮转数组 相关的讲解&#xff01;&#…

STM32:EXTI—外部中断的初始化

文章目录 1、中断1.2 中断系统1.3 中断执行流程 2、STM32中断2.2EXTI&#xff08;外部中断&#xff09;2.3 EXTI 的基本结构2.4 AFIO复用IO口 3、NVIC基本结构3.2 NVIC优先级分组 4、配置EXTI4.2 AFIO 库函数4.3 EXTI 库函数4.4 NVIC 库函数4.5 配置EXTI的步骤4.6 初始化EXTI 1…

Python运维之协程

目录 一、定义协程 二、并发 三、异步请求 协程是一种轻量级的线程&#xff0c;它通过保存和恢复寄存器上下文和栈来实现调度切换&#xff0c;从而保留函数执行的状态。 这种机制使得协程在处理I/O密集型任务时效率较高&#xff0c;因为它们可以在I/O操作期间让出CPU&#…

QT——tableWidget-跳变之舞V1.0-记录学习【1】

QT——tableWidget-跳变之舞V1.0-记录学习【1】 文章目录 QT——tableWidget-跳变之舞V1.0-记录学习【1】前言一、利用QT创建项目文件1.1 完整项目文件如下图所示:1.2 演示&#xff1a; 二、声明文件&#xff1a;2.1 主界面声明文件:mainwindow.h&#xff1b;2.2 控制窗口声明文…

科技查新中医学科研项目查新点如何确立与提炼?案例讲解

一、前言 医学科技查新包括立项查新和成果查新两个部分&#xff0c;其中医学立项查新&#xff0c;它是指在医学科研项目申报开题之前&#xff0c;通过在一定范围内进行该课题的相关文献检索 ( 可以根据项目委托人的具体要求&#xff0c;进行国内检索或者进行国外检索 ) &#x…

区块链(打新)如何被割韭菜

看上去&#xff0c;像我只要去每个都买一遍新发行的代币&#xff0c;一定可以成功的 但是好像没有想象中这么简单&#xff0c;因为这些山寨币&#xff0c;庄家可以自己控盘的&#xff0c;看上去好像有跌宕起伏的买卖&#xff0c;但是一单掀桌子&#xff0c;庄家他自己都不玩了…

Python之数据分析基础

导言&#xff1a; “21世纪的竞争是数据的竞争&#xff0c;谁掌握数据&#xff0c;谁就掌握未来”。如何将大量看似杂乱无章的数据进行聚合&#xff0c;并发现潜在的规律也变得越来越重要。本文将先说明数据分析的步骤&#xff0c;再通过python完成实例数据的处理、分析最终展…

TDM(BPM)-MIMO-FMCW雷达MATLAB仿真

本文通过对车载毫米波雷达信号流程和链路的仿真&#xff0c;建立基本的算法框架&#xff0c;可用于算法性能的验证。并提供基础MATLAB仿真代码&#xff0c;作为分享和参考。 一、信号的产生 车载毫米波雷达广泛使用线性调频连续波雷达&#xff0c;也即发射信号频率随时间线性变…

日本OTC机械手维修需要注意哪些问题呢?

随着工业4.0时代的到来&#xff0c;机器人在制造业中的应用越来越广泛。OTC&#xff08;Over The Counter&#xff09;机器人作为工业机器人的一种&#xff0c;以其高效、精准、稳定的特点受到众多企业的青睐。然而&#xff0c;在实际使用过程中&#xff0c;可能会出现一些OTC机…

如何在路由器上做端口映射

假设现在外网有一台ADSL直接拨号上网的电脑&#xff0c;所获得的是公网IP。然后它想访问局域网内的电脑上面的网站&#xff0c;那么就需要在路由器上做端口映射。在路由器上做端口映射的具体规则是&#xff1a;将所有发向自己端口的数据&#xff0c;都转发到内网的计算机。 访…