高精度算法
- 高精度加法
- 高精度减法
- 高精度乘法
- 高精度除法
高精度加法
高精度加法:反向存数组里,人工模拟两数相加
#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(); // 去除前导0for(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;
}