当我们要计算的数字比系统可以存储的最大数字还要大的时候,我们就需要使用高精度算法,也就是通过一个数组,来代替运算的过程,其中,高精度加法和高精度乘法密切相关,高精度减法和高精度除法密切相关。但是高精度除法我们不做要求。
高精度加法
主要看注释:
#include <iostream>
#include <algorithm>
using namespace std;
char a[200];
char b[200];//用来存放我要计算的数字的数组
int a1[200];
int b1[200];//用来倒叙的数组,当我们要进位的时候,如果我们按照正常的顺序的话,进位每一个数字就都要往后面移动,时间复杂度太高,所以我们选择使用倒叙,这样进位就很方便了。
int sum[201];//用来计算的数组
char out_sum[201];//把倒叙的再正过来
int main()
{
scanf("%s", a);
scanf("%s", b);
int len_a = strlen(a);
int len_b = strlen(b);
//len就是我的加法要进行的位数
int len = len_a > len_b ? len_a : len_b;
//倒叙过程
for (int i = 0; i < len_a; i++)
{
a1[len - i - 1] = a[i] - '0';
}
for (int j = 0; j < len_b; j++)
{
b1[len - j - 1] = b[j] - '0';
}
//d是用来保存进位信息的
int d = 0;
for (int i = 0; i < len; i++)
{
//当有进位信息了之后,sum就是这么计算的
sum[i] = a1[i] + b1[i] + d;
if (sum[i] > 10)
{
d = sum[i] / 10;
sum[i] %= 10;
}
else
{
d = 0;
}
}
//如果都算完了,结果还存在进位信息,那么说明我的长度要进1了
if (d > 0)
{
sum[len] += d;
len++;
}
//放到输出数组里面取
for (int i = 0; i < len; i++)
{
out_sum[i] = sum[len - 1 - i] + '0';//这里要注意要补'0'
}
for (int i = 0; i < len; i++)
{
printf("%c", out_sum[i]);
}
return 0;
}
高精度乘法
高精度乘法和高精度加法几乎一样,看图:
可以发现第i位和第j位的运算结果存放在i + j位中。存放完了之后再使用大数加法原则即可。
#include <iostream>
#include <algorithm>
using namespace std;
char a[200];
char b[200];
int a1[200];
int b1[200];
int pows[400];
char out_pow[400];
int main()
{
scanf("%s", a);
scanf("%s", b);
int len_a = strlen(a);
int len_b = strlen(b);
int len = len_a + len_b - 1;
for (int i = 0; i < len_a; i++)
{
a1[len_a - i - 1] = a[i] - '0';
}
for (int i = 0; i < len_b; i++)
{
b1[len_b - i - 1] = b[i] - '0';
}
for (int i = 0; i < len_a; i++)
{
for (int j = 0; j < len_b; j++)
{
pows[i + j] += a1[i] * b1[j];
}
}
int d = 0;
for (int i = 0; i < len; i++)
{
pows[i] += d;
if (pows[i] > 0)
{
d = pows[i] / 10;
pows[i] %= 10;
}
else
{
d = 0;
}
}
if (d > 0)
{
pows[len] += d;
len++;
}
for (int i = 0; i < len; i++)
{
out_pow[i] = pows[len - i - 1] + '0';
}
for (int i = 0; i < len; i++)
{
printf("%c", out_pow[i]);
}
return 0;
}
看看代码就行了,很好懂。
高精度减法
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
char a[200];
char b[200];
int a1[200];
int b1[200];
int sub[200];
char sub_out[200];
int main()
{
scanf("%s", a);
scanf("%s", b);
int len_a = strlen(a);
int len_b = strlen(b);
bool flag = 0;
//先判断哪个数字要大一些,我们默认让a里面的数字是大于b里面的数字的
if (len_a < len_b)//这样a必定比bu要小
{
char temp[200];
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
flag = 1;
}
else if (len_a == len_b)
{
for (int i = 0; i < len_a; i++)
{
if (a[i] < b[i])
{
char temp[200];
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
flag = 1;
break;
}
else if (a[i] > b[i])
{
break;//这个时候a一定要比b大
}
}
}
//走到这里为止,我们得到了a里面是大的数字
//开始倒叙,不然可能会发生,第一位为0的情况
for (int i = 0; i < len_a; i++)
{
a1[len_a - i - 1] = a[i] - '0';
}
for (int i = 0; i < len_b; i++)
{
b1[len_b - i - 1] = b[i] - '0';
}
int d = 0;//进位信息
int len = len_a;
for (int i = 0; i < len; i++)
{
sub[i] = a1[i] - b1[i] + d;
if (sub[i] < 0)
{
sub[i] += 10;
d = -1;
}
else
{
d = 0;
}
}
if (sub[len - 1] == 0)//如果最高位是0的话,那么我们就直接len--
{
len--;
}
for (int i = 0; i < len; i++)
{
sub_out[i] = sub[len - i - 1] + '0';
}
if (flag)
{
printf("-");
}
for (int i = 0; i < len; i++)
{
printf("%c", sub_out[i]);
}
return 0;
}
高精度除法(高精除低精度)
模拟小学除法
代码如下:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string a;
long long b;
cin >> a >> b;
long long c = 0;
long long s = 0;
long long f = 0;
for(int i = 0; i < a.size(); i++)
{
s = a[i] - '0';//把字符转换成数字
c = c * 10 + s;
f = c / b;
c = c % b;
cout << f;
}
return 0;
}