1、算法思路
对于java(有大整数类)和python来说,没有大整数计算的问题,对于c++来说,当一个整数的位数过大就会无法计算。
这里我们定义:
- 一个大整数,其长度可以在 1 0 6 10^6 106,用大写字母表示
- 一个小整数,其数值小于 1 0 9 10^9 109,用小写字母表示。
我们讨论四种类型的大整数计算
- A + B
- A - B
- A* a
- A / a
1. 数据存储
使用数组存储大整数,将低位(从个位开始)放在数组的开始,将高位放在后面,方便进位。除法其实可以正着存储,但是为了和前面统一,也要倒着存储因为一般情况下不会题目不会单独计算一个除法。
输出的
2. 运算
其实就是模拟小学手算的过程。例如对于加法 119 + 11,先算个位9 + 1进位1,然后算1 + 1 + 1 (进位),最后得到130。
3.说明
本文只给出了正整数之间的算法,至于负数、浮点数,都可以利用这个计算模板进行处理。例如有符号的数之间的计算,都可以利用这个模板进行计算。例如负数之间的运算都可以转化成正整数之间的加法或者减法再加负号。
2、模板代码
1. 大整数加法
模板
vector<int> sum(vector<int>& A,vector<int>& B)
{
vector<int> C;
int t = 0;
//从个位开始加,注意存储的时候一定要倒着存在数组里。
//这里的t != 0条件是为了A和B的最高位需要进位做处理,直接将t存入答案中
for(int i = 0; i < A.size() || i < B.size() || t != 0; i ++)
{
if(i < A.size()) t += A[i];
if(i < B.size()) t += B[i];
//获取每一位的结果并存入数组中
C.push_back(t % 10);
t /= 10;
}
//注意这里得到的结果是倒着排列的
return C;
}
2. 大整数减法
//比较A和B的数字大小
bool cmp(vector<int> &A, vector<int>& B)
{
if(A.size() != B.size())
{
return A.size() > B.size();
}
//从最高位开始一个个比较
for(int i = A.size() - 1; i >= 0; i --)
{
if(A[i] != B[i])
{
return A[i] > B[i];
}
}
//相同返回啥都行
return true;
}
//这里默认A表示的数字大于B
vector<int> sub(vector<int> &A, vector<int>& B)
{
int t = 0;
vector<int> C;
//因为A大于B,所以A的位数一定大于等于B的位数,所以只需要看A的位数即可
for(int i = 0; i < A.size(); i ++)
{
//t 在上一轮结束会被更新为借位的值,这里将借位的数减掉
t = A[i] - t;
if(i < B.size())
{
t -= B[i];
}
//这里将正负数的取模统一变成正数
// -3 + 10 之后mod 10 = 7
// 3 + 10 mod 10 = 3
C.push_back((t + 10) % 10);
//t 被更新为借位的值
if(t < 0) t = 1;
else t = 0;
}
//注意这里得到的结果是倒着排列的
//去掉前导0 ,例如对于003要去掉前面的00,在这里是去掉最后面的0
//但是又不能把所有的0去掉,例如00000 不能去没了
while(C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
3.大整数和小整数乘法
vector<int> mul(vector<int>& A, int b)
{
int t = 0;
vector<int> C;
//这里t != 0的条件依旧是为了处理最高位的进位
for(int i = 0; i < A.size() || t != 0; i ++)
{
if(i < A.size())
{
t += A[i] * b;
}
C.push_back(t % 10);
t /= 10;
}
//去除前导0
while(C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
4.大整数和小整数除法
vector<int> div(vector<int>& A , int b, int& r)
{
vector<int>& C;
r = 0;
//这里要注意,对于除法需要从最高位向后处理,我们是倒着存数据的,所以应该倒着读才是从最高位读取
for(int i = A.size() - 1; i >= 0; i --)
{
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}
//这里答案是正的,但是反过来处理比较统一
reverse(C.begin(),C.end());
while(C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}