$\Huge\color{orchid}{点击此处获取更多干货}$
高精度
C++内置的$int,long~long,float,double$类型,有效数字的位数都不太大,对于问题中达到的10万位需求,显然是不够用的,这就需要我们用字符串代替整数来进行高精度运算,可以先借助下图回忆回忆小学时学习的加法运算是怎样的:
手算加法都是把被加数(augend)和加数(addend)的最低位对齐,然后从低位向高位,把每一位数字加起来(没有的话视作0),结果的个位数字为当前数位的和,其余部分作为当前产生的进位,累加到下一位上。考虑到被加数和加数的位数可能不相同,首先要将两字符串反转,这样对齐更方便。然后就依次取得每一位的数字,模拟上述过程,此时得到的结果字符串也是倒序的,把它反转之后就是正确结果
C++ 代码
高精度的4种运算,将在代码中融合进C++的继承和多态(毕竟大家肯定都见过太多封装了)。也许对于单个问题来说继承和多态意义不大,但是如果你需要同时使用多种高精度运算,那就有必要了,因为能够让你在扩展功能的时候改动较少
基类$LargeNumCalculator$中的$calculate$函数是纯虚函数,这使得基类成为了抽象类而不能被实例化,只有继承自它并且重写了所有纯虚函数的类才可以被实例化。有兴趣的可以翻翻源码,这样的现象还是挺多的
class AddCalculator : public LargeNumCalculator{
public:
string& calculate(string augend, string addend) {
ans.clear();//原因之后解释
//被加数和加数都要反转,对齐最低位
reverse(augend.begin(), augend.end());
reverse(addend.begin(), addend.end());
int l1 = augend.size(), l2 = addend.size(), carry = 0;//carry保存上一位产生的进位
for (int i = 0; i < max(l1, l2); i++) {
//如果位数够的话,分别把加数和被加数当前数位的数字往carry上累加
if (i < l1) {
carry += (augend[i] - '0');
}
if (i < l2) {
carry += (addend[i] - '0');
}
ans += '0' + carry % 10;//carry的个位数字就是当前位产生的和
carry /= 10;//carry其余数位组成的数是当前位产生的进位
}
//最高位计算完仍然有可能产生进位(最多一位)
if (carry > 0) {
ans += '0' + carry;
}
//去掉前导0
while (ans.size() > 1 && ans.back() == '0') {
ans.pop_back();
}
//ans此时是倒序的,还需要反转回来
reverse(ans.begin(), ans.end());
return ans;
}
};
## 6