本篇文章是依据哔哩哔哩上up主麦克老师讲算法的视频做的笔记,该视频简单易懂,十分推荐,推荐看视频。
【高精度算法全套(加,减,乘,除,全网最详细)】 https://www.bilibili.com/video/BV1LA411v7mt/?share_source=copy_web&vd_source=5ebb8be0e4868c8d7bbd5edd0ee2e04d
int类型的取值范围10^9,long long类型为10^18,当要取得的数据大于这个范围就需要使用高精度了。
高精度加法
问题描述:求A加B
a4 a3 a2 a1
+ b4 b3 b2 b1
--------------------
c5 c4 c3 c2 c1
算法核心
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;
c[i]=c[i]%10;
例题为洛谷P1601 A+B Problem(高精)
题目描述
高精度加法,相当于 a+b problem,不用考虑负数。
输入格式
分两行输入。a,b<=10^500。
输出格式
输出只有一行,代表 a+b 的值。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int c[505];
int main()
{
size_t asbut=0, bsbut=0;
string a, b;
cin >> a >> b;
//反转输入内容方便后期计算
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
asbut = a.size(), bsbut = b.size();
int i;
for (i = 0; i < max(asbut, bsbut); i++)
{
if (i > min(asbut, bsbut)-1) { //当相加的数位数不一样时,需要对长的那位单独做,因为用的是string,不单独做的话,会访问错误
if (a.size() == min(asbut, bsbut)) {
c[i] += b[i]-'0';
c[i + 1] = c[i] / 10;
c[i] = c[i] % 10;
}
if (b.size() == min(asbut, bsbut)) {
c[i] += a[i] - '0';
c[i + 1] = c[i] / 10;
c[i] = c[i] % 10;
}
}
else { //如果相加的两位数都是用int数组保存好的话,就不需要上面判断位数不相等的部分了
c[i] += (a[i] - '0') + (b[i] - '0');
c[i+1] = c[i] / 10;
c[i] = c[i] % 10;
}
}
if (c[i] ==0 ) {
i--;
}
for (int j = i; j >=0; j--) {
cout << c[j];
}
return 0;
}
感觉还是全部用数组做方便了
高精度减法
问题描述:求A-B
a4 a3 a2 a1
- b4 b3 b2 b1
--------------------
c5 c4 c3 c2 c1
算法核心:
如果a<b,则需要交换a和b;
如果a[i]<b[i],需要高位借1当10用
if(a[i]<b[i]){
a[i+1]--;
a[i]+=10;
}
c[i]=a[i]-b[i];
例题为洛谷题目p2142高精度减法
题目描述
高精度减法。
输入格式
两个整数 a,b(第二个可能比第一个大)。
输出格式
结果(是负数要输出负号)。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int a[11000],b[11000],c[11000];
int main()
{
int flag = 0;
string s1, s2;
cin >> s1 >> s2;
size_t la, lb, lc;
//判断s1和s2的长度,s1小于s2的话就互相交换
if (s1.size() < s2.size()) {
flag = 1;
swap(s1, s2);
}
//当s1和s2一样长是,就比较对应位置字符的字典大小,s1小于s2的话,互相交换
if (s1.size() == s2.size()) {
if (lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end())){
flag = 1;
swap(s1, s2);
}
}
//将字符串的长度装起来,注意la,lb,lc的型别
la = s1.size();
lb = s2.size();
lc = max(la, lb);
//将字符串对应的字符,转换成整型保存起来,方便后面进行计算
for (int i = 0; i < la; i++) {
a[la - i] = s1[i] - '0';
}
for (int i = 0; i < lb; i++) {
b[lb - i] = s2[i] - '0';
}
//进行减法计算
for (int i = 1; i <= lc;i++) {
if (a[i] < b[i]) {
a[i + 1]--;
a[i] += 10;
}
c[i] = a[i] - b[i];
}
//去掉前置0
while (c[lc] == 0 && lc > 1) {
lc--;
}
//判断是否进行了交换,进行了的话,则输出-
if (flag == 1) {
cout << '-';
}
for (int i = lc; i > 0; i--) {
cout << c[i];
}
cout << endl;
return 0;
}
高精度乘法
问题描述A*B:
a4 a3 a2 a1
* b2 b1
--------------------
c5 c4 c3 c2 c1
核心算法:
a[i]*b[i]=c[i+j-1];
考虑进位
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
例题为p1303 A*B problem
题目描述
给出两个非负整数,求它们的乘积。
输入格式
输入共两行,每行一个非负整数。
输出格式
输出一个非负整数表示乘积。
#include<iostream>
#include<string>
using namespace std;
int a[10000], b[10000],c[10000];
int main(){
string s1, s2;
cin >> s1 >> s2;
size_t la, lb, lc;
la = s1.size(), lb = s2.size();
//将类型转换成int进行保存,方便计算
for (int i = 1; i <= la; i++) {
a[i] = s1[la - i]-'0';
}
for (int i = 1; i <= lb; i++) {
b[i] = s2[lb - i]-'0';
}
//进行乘法计算了
lc = la + lb;
for (int i = 1; i <= la; i++) {
for (int j = 1; j <= lb; j++) {
c[i + j - 1] += a[i] * b[j];
c[i + j] += c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
}
//去前置0
while (c[lc] == 0 && lc > 1)lc--;
//打印
for (int i = lc; i > 0; i--) {
cout << c[i];
}
cout << endl;
return 0;
}