使用C++实现,代码有注释。
实现思路:
1. 将加法分解成三个小问题:
a. 两个都是正整数
b. 两个都是负整数
c. 一个正数,一个负数
2. 两个正整数相加算法:
a. 主加循环:倒序遍历。两个整数按照最低位对齐,从最低位开始相加,每次相加时记录是否有进位,有进位时设置extra = 1,同时将相加的结果减10,无进位是设置extra = 0,相加的结果不变,将相加的结果插入到结果字体串中,进位会在下一位相加时使用;
b. 当两个数字的位数相等时,加了最后一位后退出循环,退出循环后检查是否有进位,即extra是否为1,如果是,说明两个m位数相加得出了一个m+1位数字,将进位1添加到未尾;
c. 当两个数字位数不相等时,退出“主加循环”后,将更长位数的数字其他部分按倒序插入到结果字体串中,同时也要判断extra的情况;
d. 将字符串进行反转,即可得出结果。
3. 两个负数相加
a. 将负号提取出来,使用两个正整数相加算法,最后再将负号添加回去。
4. 一个正数,一个负数
a. 这种情况下,首先要判断那个数字的绝对值更大,如果是负数的绝对值更大,最后的结果会是负数,如果是正数的绝对值更大,最后的结果会是正数,当两个数字除符号位相等时,结果为0;
b. 在步骤a肯定了符号(正负号),然后取两个数字的绝对值,绝对值大的作为被减数,绝对值小的作为减数,得出结果。减运算的算法和两个正数相加类似,只不过减的时候extra会是-1或者0。
#include <iostream>
#include <cstring>
#include <string>
//辅助函数
void reverse(std::string& str)
{
if (str.size() <= 1)
{
return;
}
char ch;
for (int i = 0; i < str.size() / 2; ++i)
{
ch = str[i];
str[i] = str[str.size() - 1 - i];
str[str.size() - 1 - i] = ch;
}
}
//辅助函数,用于减法中,str2为负数
int compare(const std::string& str1, const std::string& str2)
{
if (str1.size() + 1 == str2.size())
{
int n = 0;
for (int i = 0; i < str1.size(); ++i)
{
if (str1[i] == str2[i + 1])
{
++n;
}
}
if (n == str1.size())
{
return 0;
}
}
if (str1.size() + 1 > str2.size())
{
// str1的绝对值更大
return 1;
}
if (str1.size() + 1 < str2.size())
{
// str2的绝对值更大
return -1;
}
for (int i = 0; i < str1.size(); ++i)
{
if (str1[i] > str2[i + 1])
{
return 1;
}
else if (str2[i + 1] > str1[i])
{
return -1;
}
}
}
//辅助函数:这里的str1和str2都是正整数,而且str1比str2大
std::string sub(const std::string& str1, const std::string& str2, const std::string& ch = "+")
{
std::string ret;
//ret.reserve(str1.size());
int extra = 0;
int tail_1 = str1.size() - 1;
int tail_2 = str2.size() - 1;
int sub = 0;
while (tail_1 >= 0 and tail_2 >= 0)
{
int a = str1[tail_1] - '0' + extra;
int b = str2[tail_2] - '0';
if (b > a)
{
sub = 10 + a - b;
extra = -1;
}
else
{
sub = a - b;
extra = 0;
}
ret.push_back(sub + '0');
--tail_1;
--tail_2;
}
while (tail_1 >= 0)
{
int a = str1[tail_1] - '0' + extra;
ret.push_back(a + '0');
extra = 0;
--tail_1;
}
reverse(ret);
for (std::string::iterator it = ret.begin(); it != ret.end();)
{
if (*it == '0')
{
it = ret.erase(it);
}
else if (*it != '0')
{
break;
}
}
if (ch == "-")
{
ret.insert(0, ch);
}
return ret;
}
//大数加法
//两个正整数相加
std::string add_positive(const std::string& str1, const std::string& str2)
{
if (str1.size() < 1 or str2.size() < 1)
{
return 0;
}
int tail = 0;
if (str1[0] == '-' and str2[0] == '-')
{
tail = 1;
}
int extra = 0;
int sum = 0;
int length = str1.size() > str2.size() ? str1.size() : str2.size();
std::string total;
total.reserve(length + 1 + 1);
int tail_1 = str1.size() - 1;
int tail_2 = str2.size() - 1;
while (tail_1 >= tail and tail_2 >= tail)
{
sum = (str1[tail_1] - '0') + (str2[tail_2] - '0') + extra;
if (sum >= 10)
{
extra = 1;
sum -= 10;
}
else
{
extra = 0;
}
total.push_back(sum + '0');
--tail_1;
--tail_2;
}
while (tail_1 >= tail)
{
sum = (str1[tail_1] - '0') + extra;
if (sum >= 10)
{
extra = 1;
sum -= 10;
}
else
{
extra = 0;
}
total.push_back(sum + '0');
--tail_1;
}
while (tail_2 >= tail)
{
sum = (str2[tail_2] - '0') + extra;
if (sum >= 10)
{
extra = 1;
sum -= 10;
}
else
{
extra = 0;
}
total.push_back(sum + '0');
--tail_2;
}
if (extra != 0)
{
total.push_back(extra + '0');
}
reverse(total);
return total;
}
//两个整数相加, str2是负数
std::string add_negative(const std::string& str1, const std::string& str2)
{
int length = str1.size() > str2.size() ? str1.size() : str2.size();
std::string ret;
ret.reserve(length + 1 + 1);
int flag = compare(str1, str2);
if (flag == 0)
{
return std::string("0");
}
else if (flag == 1)
{
std::string nstr2 = str2;
nstr2.erase(nstr2.begin());
return sub(str1, nstr2);
}
else
{
std::string nstr2 = str2;
nstr2.erase(nstr2.begin());
return sub(nstr2, str1, "-");
}
}
//两个都是负数
std::string sub_negative(const std::string& str1, const std::string& str2)
{
if (str1.size() < 1 or str2.size() < 1 or str1[0] != '-' or str2[0] != '-')
{
return 0;
}
std::string ret = add_positive(str1, str2);
ret.insert(0, "-");
return ret;
}
//约定正整数不会出现“+”号,负数必有“-”号
std::string add_big_number(const std::string& str1, const std::string& str2)
{
if (str1.size() < 1 or str1.size() < 1)
{
return 0;//实际中应该返回某种错误
}
if (str1.size() == 1 && (str1[0] == '+' or str1[0] == '-'))
{
return 0;
}
if (str2.size() == 1 && (str2[0] == '+' or str2[0] == '-'))
{
return 0;
}
if (str1[0] != '-' && str2[0] != '-')
{
return add_positive(str1, str2);
}
else if (str1[0] == '-' && str2[0] != '-')
{
return add_negative(str2, str1);
}
else if (str1[0] != '-' && str2[0] == '-')
{
return add_negative(str1, str2);
}
else
{
return sub_negative(str1, str2);
}
}
int main()
{
std::string str1("-545456563565656565665555555565564565465440");
std::string str2("5456565466666666665465654656565656546546544540");
std::string ret = add_big_number(str1, str2);
std::cout << ret << std::endl;
int a = 1;
std::cin.get();
}