高精度加法
高精度加法:反向存数组里,人工模拟两数相加
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string s1, s2;
void add(vector<int>& A, vector<int>& B)
{
vector<int> c;
int t = 0;
for(size_t i = 0; i < A.size() || i < B.size(); i++)
{
int ret = t;
if(i < A.size()) ret += A[i];
if(i < B.size()) ret += B[i];
c.push_back(ret % 10);
t = ret / 10;
}
if(t > 0) c.push_back(t);
for(int i = c.size() - 1; i >= 0; i--)
{
cout << c[i];
}
}
int main()
{
vector<int> A;
vector<int> B;
cin >> s1 >> s2;
for(int i = s1.size() - 1; i >= 0; i--) A.push_back(s1[i] - '0');
for(int i = s2.size() - 1; i >= 0; i--) B.push_back(s2[i] - '0');
add(A, B);
return 0;
}
高精度减法
高精度减法
将大数字符串反向存在数组里,保证算法实现的时候为较大数 - 较小数
,所以要添加一个比较函数 cmp
,如果题目是 小 - 大
,要给最终结果前面加一个负号
- 比较函数
cmp
,保证算法里是大 - 小
;实现时,先判断 size 相等的情况,依次比较每一位,这些位中,如果哪一位不相等,就直接 return,如果不相等就直接返回 size 是否较大 flag
标志,flag 的值决定是否在打印前先输出-
- 前导零的处理,前导零是直接出现在 C 的末尾的,直接判断再 pop 即可
- 可以逆置,也可以不逆置,不逆置就反正输出即可
易错点:算法在实现的过程中,循环次数是 A.size()次,同时在循环里判断是否要减去 B[i]
,因为 B 有可能会越界,用 A来循环时为了保证 减完 B 之后方便将余下的借位处理掉
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool flag = 1;
bool Cmp(vector<int>& A, vector<int>& B)
{
if(A.size() == B.size())
{
for(int i = A.size() - 1; i >= 0; i--)
{
if(A[i] != B[i]) return A[i] > B[i];
}
}
return A.size() >= B.size(); // 包含 A == B
}
int Sub(vector<int>& A, vector<int>& B)
{
vector<int> C;
int t = 0; // 被借的位
for(size_t i = 0; i < A.size(); i++)
{
t = A[i] - t;
if(i < B.size()) t -= B[i];
C.push_back((t + 10) % 10); // 完美解决 t > 0 和 t < 0 的情况
if(t < 0) t = 1;
else t = 0;
}
for(size_t i = C.size(); i < A.size(); i++) C.push_back(A[i]);
// 删除前导零
while(C.size() > 1 && C.back() == 0) C.pop_back();
if(!flag) cout << "-";
for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
}
int main()
{
string a, b;
cin >> a >> b;
vector<int> A, B;
for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
for(int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
if(!Cmp(A, B))
{
flag = 0;
swap(A, B);
}
Sub(A, B);
}
高精度乘法
高精度 * 低精度
将高精度存在数组里,低精度看作一个整体,模拟人工乘法,注意处理进位
当两个数中有 0 时,可特判,也可当前导零直接处理
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Mul(vector<int>& A, int b)
{
vector<int> C;
int t = 0;
for(size_t i = 0; i < A.size() || t > 0; i++)
{
if(i < A.size()) t = A[i] * b + t;
C.push_back(t % 10);
t /= 10;
}
while(C.size() > 1 && !C.back()) C.pop_back(); // 去除 A 或 b 为 0 时导致的前导 0
// reverse(C.begin(), C.end()); // 可以逆序后再按序输出, 也可以直接输出
// for(size_t i = 0; i < C.size(); i++) cout << C[i];
for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
}
int main()
{
string a;
int b;
cin >> a >> b;
vector<int> A;
for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
Mul(A, b);
return 0;
}
高精度除法
高精度 / 低精度 --> 商 和 余数,计算出的余数可以当作取模运算的结果
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Div(vector<int>& A, int b)
{
vector<int> C; // 存结果
int t = 0;
int rem; // 存余数
for(int i = A.size() - 1; i >= 0; i--)
{
t = t * 10 + A[i];
C.push_back(t / b);
t %= b;
}
rem = t;
reverse(C.begin(), C.end());
while(C.size() > 1 && !C.back()) C.pop_back(); // 去除前导0
for(int i = C.size() - 1; i >= 0; i--) cout << C[i]; // 输出商
cout << endl << rem; // 输出余数
}
int main()
{
string a;
int b;
vector<int> A;
cin >> a >> b;
for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
Div(A, b);
return 0;
}