处理加减法的逻辑都是处理正数,提前把符号问题处理好,然后做两个正数的加减法

做减法时,直接用字符串比较的方法,就能选出数值较大的大数,然后用大数减小数,最后添加负号即可

#include <iostream>
#include <string>
#include <algorithm>//泛型算法

using namespace std;

//编程题目:请实现以下类的方法,完成大数的加减法
class BigInt{
public:
BigInt(string str) {
sign = (str[0] == '-') ? '-' : '+';
if (sign == '-') {
str_num = string(str.begin() + 1, str.end());
}
else {
str_num = str;
}
}

private:
string str_num; //存储不带符号的字符串
char sign;

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){
if (src.sign == '-') {
out << '-';
}
out << src.str_num;
return out;
}

//大数加法
BigInt operator+(const BigInt& lhs, const BigInt& rhs){
string result;//存储计算的结果
bool carry = false;//需不需要考虑进位
string num_l = lhs.str_num;
string num_r = rhs.str_num;
bool add_minus = false;

if (lhs.sign == '-' && rhs.sign == '-') {
// 两个负数相加
add_minus = true;
}
else if (lhs.sign == '-') {
// 只有lhs是负数
return BigInt(num_r) - BigInt(num_l);
}
else if (rhs.sign == '-') {
// 只有rhs是负数
return BigInt(num_l) - BigInt(num_r);
}

/*
遍历字符串l,r,从后往前遍历
同位置的数字相加, 进位 flag 存入一个结果当中 string result
同时完成
某个字符串先完成 都要考虑进位
*/

int i = num_l.length() - 1; //
int j = num_r.length() - 1; //有效字符的长度

//从后往前遍历,从个位加
for (; i >= 0 && j >= 0; --i, --j){
int ret = num_l[i] - '0' + num_r[j] - '0';
if (carry){
// 有进位
ret += 1;
carry = false;
}

if (ret >= 10){
ret %= 10;//取余数 13就是取3
carry = true;
}
result.push_back(ret + '0');//尾部添加,从个位开始计算
}

//i j
//第一个字符串还没完
if (i >= 0){
while (i >= 0){
int ret = num_l[i] - '0';
if (carry){
ret += 1;
carry = false;
}

if (ret >= 10){
ret %= 10;
carry = true;
}
result.push_back(ret + '0');
i--;
}
}
else if (j >= 0) {
//第二个字符串还没完
while (j >= 0){
int ret = num_r[j] - '0';
if (carry){
ret += 1;
carry = false;
}

if (ret >= 10){
ret %= 10;
carry = true;
}
result.push_back(ret + '0');
j--;
}
}

//进位
if (carry){
result.push_back('1');
}
if (add_minus) {
result.push_back('-');
}
reverse(result.begin(), result.end());//翻转字符串
return result;//return BigInt(result)
}

//大数减法
BigInt operator-(const BigInt& lhs, const BigInt& rhs){
string num_l = lhs.str_num;
string num_r = rhs.str_num;

if (lhs.sign == '-' && rhs.sign == '-') {
// 两个负数相减
return BigInt(num_r) - BigInt(num_l);
}
if (lhs.sign == '-') {
// 只有lhs是负数
return BigInt("0") - (BigInt(num_l) + BigInt(num_r));
}
if (rhs.sign == '-') {
// 只有rhs是负数
return BigInt(num_l) + BigInt(num_r);
}

/*
找大的字符串左减数,小的左被减数
遍历两个字符串,减法,借位(bool flag), string result存下来
*/
string result;
bool borrow = false; // 借位
bool minor = false; // 最终的结果是否输出负号

string maxStr = num_l;
string minStr = num_r;
//确定大小字符串
if (maxStr.length() < minStr.length()){
// lhs长度小于rhs
maxStr = num_r;
minStr = num_l;
minor = true;//结果要添加负号
}else if (maxStr.length() == minStr.length()){
//长度相等
if (maxStr < minStr) {
//string类重载<,实现字符串比较大小
maxStr = num_r;
minStr = num_l;
minor = true;
}
else if (maxStr == minStr){
// 长度相等,内容也相等,说明两个字符串相等
return string("0");
}
}

int i = maxStr.length() - 1;
int j = minStr.length() - 1;

for (; i >= 0 && j >= 0; --i, --j)//从后向前,个位开始减起
{
int ret = maxStr[i] - minStr[j];
if (borrow)//借位了
{
ret -= 1;
borrow = false;
}

if (ret < 0)
{
ret += 10;
borrow = true;
}
result.push_back(ret + '0');
}

while (i >= 0)
{
int ret = maxStr[i] - '0';
if (borrow)
{
ret -= 1;
borrow = false;
}

if (ret < 0)
{
ret += 10;
borrow = true;
}

result.push_back(ret + '0');
i--;
}

string retStr;
auto it = result.rbegin();
for (; it != result.rend(); ++it){
if (*it != '0'){
break;//把0过滤掉
}
}
for (; it != result.rend(); ++it){
retStr.push_back(*it);
}
//100000
if (minor){
retStr.insert(retStr.begin(), '-');
}

return retStr;
}

int main(){
BigInt int4("-354565489454645231");
BigInt int5("41326354687656452898965765453");
cout << int4 - int5 << endl;
return 0;
}