一.思想
高精度算法在处理超级大数字的时候是十分必要的,用数组来模拟四则运算的过程,也是很简单的算法,在小学时期就学过四则运算的法则,在纸上模拟一遍就会了。
二.高精度加法
题目:
#include <bits/stdc++.h>
using namespace std;
int a[505000], c[505000], b[505000];//a为数字1,b为数字2,c来存答案
string e, f;//因为数太大用string先存着
int main()
{
cin >> e >> f;
int le = e.size();
int lf = f.size();
for (int i = 1; i <= le; i++)//根据运算法则逆位存储
{
a[i] = e[le - i] - '0';
cout << a[i];
}
for (int i = 1; i <= lf; i++)//同理 逆位存储
b[i] = f[lf - i] - '0';
int lc = max(e.size(), f.size()) + 1;//c数组大小大1,因为可能有进位
for (int i = 1; i <= lc; i++)
{
c[i] += b[i] + a[i];//先讲a数组和b数组的位数相加
c[i + 1] = c[i] / 10;//进位
c[i] = c[i] % 10;//当前位置的值,%即可得到
}
while (c[lc] == 0 && lc > 0)//去前导0
lc--;
for (int i = lc; i > 0; i--)//反向输出
cout << c[i];
}
二.高精度减法
#include <bits/stdc++.h>
using namespace std;
string e, f, g;
int le, lf, flag = 0;
int a[100005], b[100005], c[100005];//c存答案的数组
bool cmp(string e, string f)
{
if (le != lf)//先看长度
return le > lf;
for (int i = 0; i < le; i++)//长度一样 看位数大小
{
if (e[i] != f[i])
return e[i] > f[i];
}
return false;//相同的情况
}
int main()
{
cin >> e >> f;
le = e.size();
lf = f.size();
if (!cmp(e, f))//一定要把大的数放在前面!
{
swap(e, f);
swap(le, lf);
flag = 1;//记得变号哦
}
for (int i = 1; i <= le; i++)//反向存储
{
a[i] = e[le - i] - '0';
}
for (int i = 1; i <= lf; i++)//反向存储
{
b[i] = f[lf - i] - '0';
}
int lc = max(le, lf);
for (int i = 1; i <= lc; i++)
{
if (a[i] < b[i])//按照减法运算可以轻易得出
{
a[i + 1]--;//前位取1
a[i] += 10;//这位进10
}
c[i] = a[i] - b[i];//一减就是该位数
}
while (c[lc] == 0 && lc > 0)//去前导0
lc--;
if (flag == 1)//换数了的话记得变号哦
cout << '-';
for (int i = lc; i > 0; i--)//反向输出
cout << c[i];
return 0;
}
有几点需要注意:
1.要把大的放在前面。
2.换数要变号。
三.高精度乘法
大数乘小数
这个用一下stl和数组模拟差不多,但是数组不好确定最终答案c的长度,其实还是stl好用点,但是会一个也就会另一个。
#include <bits/stdc++.h>
using namespace std;
string s;
vector<int> a, c;//都是老样子了
int b;
int main()
{
cin >> s;
cin >> b;
for (int i = s.size() - 1; i >= 0; i--)// 依旧反向存储./
{
a.push_back(s[i] - '0');
}
int t = 0;
for (int i = 0; i < a.size() || t; i++)//注意这个t哦 万一有剩余的余数可以给他加上
{//根据四则运算很好得出下面
if (i < a.size())
t += a[i] * b;
c.push_back(t % 10);//老样子%为该数
t /= 10;//进位
}
while (c.size() > 1 && c.back() == 0)
c.pop_back();//去前导0
for (int i = c.size() - 1; i >= 0; i--)//依旧反向输出./
cout << c[i];
return 0;
}
大数乘大数
两个超级大数相乘 上代码:
#include <bits/stdc++.h>
using namespace std;
string s1, s2;
int a[100005], b[100005], c[100005];
int main()
{
cin >> s1 >> s2;
int la = s1.size();
int lb = s2.size();
if(la==1&&s1[0]==0)
{
cout << 0;
return 0;
}
if(lb==1&&s2[0]==0)
{
cout << 0;
return 0;
}
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';
}
int 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;
}
}
while (c[lc] == 0 && lc > 0)
lc--;
for (int i = lc; i > 0; i--)
{
cout << c[i];
}
return 0;
}
我们可以得出a的下标加b的下标再减一就是c的下标!!!
四.高精度除法
#include <bits/stdc++.h>
using namespace std;
int a[1000005], b;
string s;
int c[100005];
int main()
{
int x = 0;
cin >> s >> b;
int la = s.size();
if (s[0] == '0')
{
cout << 0;
return 0;
}
for (int i = 0; i < la; i++)//根据除法法则 不用逆序存储
a[i] = s[i] - '0';
for (int i = 0; i < la; i++)
{//根据除法运算也很好得出
c[i] = (x * 10 + a[i]) / b;//该数字等于余数乘10+下面的数再除以b
x = (x * 10 + a[i]) % b;//求余数
}
int lc = 0;
while (c[lc] == 0 && lc + 1 < la)//去前导0
lc++;
for (int i = lc; i < la; i++)//不用逆序存储也不用逆序输出
{
cout << c[i];
}
cout << endl;
cout << x;
return 0;
}
总结
高精度还是比较简单的,但是需要巩固和训练,多敲几遍即可烂熟于心!!!加油努力!!!