当运算数据超过int,long long的范围时,我们就需要运用高精度算法来计算。其基本思想我总结为,将输入的数据以字符的形式存入,对两组数据同位数字进行运算,找到各位之间的关系,以此来进行大数的加减乘除。
高精度加法
#include <bits/stdc++.h>
using namespace std;
long long s1[505];
long long s2[505];
long long s3[505]; //用于输出最终答案
int main() {
string str1, str2;
cin >> str1 >> str2;
int l1 = str1.size();
int l2 = str2.size();
for (int i = 0; i < l1; i++) //将数据反向存入,依次从小位到大位的进制
s1[l1 - i] = str1[i] - '0';
for (int i = 0; i < l2; i++)
s2[l2 - i] = str2[i] - '0';
int l3 = max(l1, l2) + 1; //两数相加可能会往后进一位,因此需要长度加一
for (int i = 1; i <= l3; i++) { //这一部分是算法的主体,这里的思想就是小学时将两
个数叠在一起的计算思路
s3[i] = s3[i] + s1[i] + s2[i];
s3[i + 1] = s3[i] / 10;
s3[i] = s3[i] % 10;
}
if (s3[l3] == 0 && l3 > 1) //这里判断两个数字相加之后最高位是否改变
l3--;
for (int i = l3; i > 0; i--) {
cout << s3[i];
}
return 0;
}
高精度减法
高精度加法的主要思路与加法相同,但在一开始减数与被减数的选择上有所侧重,这与不同高精度减法方法不同有很大的关系,我这里是将输入的两个数进行比较,将大的数放在前面。
#include <bits/stdc++.h>
using namespace std;
long long s1[10100] = {0};
long long s2[10100] = {0};
long long s3[10100] = {0};
int main() {
string str1, str2;
cin >> str1 >> str2;
int l1 = str1.size();
int l2 = str2.size();
for (int i = 0; i < l1; i++)
s1[l1 - i] = str1[i] - '0';
for (int i = 0; i < l2; i++)
s2[l2 - i] = str2[i] - '0';
int p; //p=1和p=0来表示两个数谁大谁小
if (l1 < l2)
p = 0;
else {
if (l1 > l2)
p = 1;
else {
for (int i = l1; i >= 0; i--) { //从高位往低位依次比较数字大小来判断
if (s1[i] > s2[i]) {
p = 1;
break;
} else if (s1[i] < s2[i]) {
p = 0;
break;
} else if (i == 0 && s1[i] == s2[i]) {
p = 1;
}
}
}
}
int l3 = max(l1, l2) ; //由于两个数相减不会出现进位的情况,因此
不用加一
int k;
for (int i = 1; i <= l3; i++) {
if (p == 1) {
if (s1[i] < s2[i]) {
s1[i + 1]--;
s1[i] += 10;
}
s3[i] = s1[i] - s2[i];
} else {
if (s1[i] > s2[i]) {
s2[i + 1]--;
s2[i] += 10;
}
s3[i] = s2[i] - s1[i];
}
}
while (s3[l3] == 0 && l3 > 1) //两个数高位相减可能会刚好减完,需要判断
l3--;
for (int i = l3; i > 0; i--) {
if (p == 0) {
if (i == l3) {
cout << '-' << s3[i];
} else
cout << s3[i];
} else {
cout << s3[i];
}
}
return 0;
}
高精度乘法
首先我们先来用小学生的方法计算两个数的相乘,通过观察我们不难发现,C的下标=a的下标+b的下标+1,因此整体算法与加法相似。
#include <bits/stdc++.h>
using namespace std;
long long s1[1000000];
long long s2[1000000];
long long s3[1000000];
int main() {
string str1, str2;
cin >> str1 >> str2;
int l1 = str1.size();
int l2 = str2.size();
for (int i = 0; i < l1; i++)
s1[l1 - i] = str1[i] - '0';
for (int i = 0; i < l2; i++)
s2[l2 - i] = str2[i] - '0';
int l3 = l1 + l2; //前面我们已经知道c=a+b+1
for (int i = 1; i <= l1; i++) {
for (int j = 1; j <= l2; j++) {
s3[i + j - 1] = s3[i + j - 1] + s1[i] * s2[j];
s3[i + j] += s3[i + j - 1] / 10; //注意这里是+=,具体为什么自己推一推吧,
s3[i + j - 1] = s3[i + j - 1] % 10; //毕竟是小学二年级的内容哈
}
}
if (s3[l3] == 0 && l3 > 0) //注意这里的条件是l3>0,而不是l3>1;
l3--;
for (int i = l3; i > 0; i--) {
cout << s3[i];
}
return 0;
}
高进度除法
高进度除法分为高精度除以低精度和高精度除以高精度两种情况
高精度除以低精度
运用小学所学的逐位试商法,是个求商和求余的过程
#include <bits/stdc++.h>
using namespace std;
long long s1[1000000];
long long s3[1000000];
int main() {
string str1;
long long b;
long long x = 0;
cin >> str1 >> b;
int l1 = str1.size();
for (int i = 1; i <= l1; i++) { //由于是除法,所以不需要倒着输入
s1[i] = str1[i - 1] - '0';
}
for (int i = 1; i <= l1; i++) {
s3[i] = (x * 10 + s1[i]) / b;
x = (x * 10 + s1[i]) % b;
}
long long l3 = 1;
while (s3[l3] == 0 && l3 < l1) { //删除前面的所有0;
l3++;
}
for (int i = l3; i <= l1; i++) { //注意这里i的范围
cout << s3[i];
}
return 0;
}
高精度除以高精度
由于除数和被除数都是很大的数,显然无法通过long long来存储了,那么这里又需要用到一种新的方法——减法模拟除法
家人们看懂了吗,ok,接下来就是算法了
额,这个我现在好像也不太会,过几天再来写吧