前言
高精度算法就是为了去解决一些比较大的数,这些数大到long long都存不下。,这里的主要思想就是用字符串来存。
下面的内容有很多用到c++的容器,不明白的可以先去学习stl。
一 高精度加法
首先第一步就是去模拟我们自己写的加法,,从我们自己写的加法上面来看,第一它是从个位开始加,如果大于10就会产生进位,这个进位要加到下一位去。
我们写加法是从个位开始,但是用代码去写,就需要倒过来,因为个位是不好去进位的,如果用个位去进位,那么就会导致整块的移动,这样效率就会很低了
图一是我们自己算,图二则是我们用代码去实现的过程
所以有了上面的准备,就可以写出下面代码
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(const vector<int>& A, const vector<int>& B)//加法函数,这里传引用是为了提高效率
{
int t = 0;
vector<int>C;//用来返回
for (int i = 0; i < A.size(); i++)//因为之前已经逆序了,所以这里直接从0开始遍历
{
t +=A[i];//首先把最长的数的最后一位加上
if (i < B.size()) t += B[i];//因为B短,所以我们需要去判断B是否已经结束
C.push_back(t % 10);//最后我们是插入t%10,如果大于就进位,小于就不进位
t /= 10;//这里相当于是进位的过程
}
if (t) C.push_back(1);//还有A结束的时候,可能还有一个进位没有处理,这里把它尾插
return C;
}
int main()
{
string a, b;
vector<int>A, B, C;
cin >> 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 (A.size() > B.size()) C = add(A, B);//这里是调整A,B那个数长,长的放上面,比较好操作
else C = add(B, A);
for (int i = C.size()-1; i >= 0; i--)//因为是逆序相加的,所以这里需要再逆序倒过来输出
{
cout << C[i];
}
cout << endl;
return 0;
}
主函数里面的处理还是比较简单的,关键在于两个数的相加
二 高精度减法
其实减法也差不多,一样的反转,但是不同的就是我们需要用一个数去存一个借位,而不是进位,因为一个数减另外一个数不够我们就需要去借位,这样才能够减,第二就是我们在进行减法的时候需要的是去判断两个数的大小哪个更加大,而不是和加法一样去判断长度。
一样的,下面看代码理解
bool cmp(vector<int>& A, vector<int>& B)//比较函数
{
if (A.size() != B.size())
return A.size() > B.size();
for (int i = A.size() - 1; i >= 0; i--)
{
if (A[i] != B[i])
return A[i] > B[i];
}
return true;
}
vector<int> sub(vector<int>& A, vector<int>& B)//减法函数
{
int t = 0;
vector<int>C;
for (int 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,说明没有借位,如果小于0,就借位了
//这里+10是先算它进位,然后再%10,如果没有进位,那就是它本身
//如果进位了,那我们插入的就是10-t;
if (t < 0) t = 1;//借位等于1,下次循环,A[i]就需要-1
else t = 0;
}
while (C.size() > 1 && C.back() == 0)C.pop_back();//这里需要去掉前导零
return C;
}
int main()
{
string a, b;
vector<int>A, B, C;
cin >> 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)) C = sub(A, B);//这是判断大小
else C = sub(B, A), cout << '-';//如果A小于B,那么我们可以换成-(B-A)
//这里要多输出一个符号
for (int i = C.size()-1; i >= 0; i--)
{
cout << C[i];
}
cout << endl;
return 0;
}
三 高精度乘法
关于高精度乘法来说,就没有减法那么多处理了,甚至比加法还简单一点,这里的乘法是一个多位数和一个低位数的相乘
vector<int> mul(vector<int>& A, int b)
{
int t = 0;
vector<int>C;
for (int i = 0; i < A.size(); i++)
{
t += A[i] * b;//t是进位
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(t);//最后一位有进位就插入
while (C.size() > 1 && C.back() == 0) C.pop_back();//处理前导零
return C;
}
int main()
{
string a;//这里直接正常操作就行
int b;
vector<int>A, C;
cin >> a >> b;
for (int i = a.size()-1; i >=0; i--)
{
A.push_back(a[i] - '0');
}
C = mul(A, b);
for (int i = C.size()-1; i >= 0; i--)
{
cout << C[i];
}
cout << endl;
return 0;
}
四 高精度除法
这里的除法和其他的又有点不一样,但是不一样的不会很多,第一就是我们除一个数可能除不尽,所以这里需要一个余数去存。
vector<int> div(vector<int>& A, int b,int &r)
{
r = 0;
vector<int>C;
for (int i = A.size()-1; i >= 0; i--)//这里和其他的不一样,因为我们除法只能从个位开始除
{
r = r * 10 + A[i];//这里表示余数和下一个数的相加
C.push_back(r / b);
r %= b;
}
reverse(C.begin(), C.end());//这里因为上面的操作把C变为正序了,所以这里要反过来,因为
//后面打印是按逆序打印,这里就和上面同一了
while (C.size() > 1 && C.back() == 0)C.pop_back();//去前导零
return C;
}
int main()
{
string a;
int b;
vector<int>A, C;
cin >> a >> b;
for (int i = a.size()-1; i >=0; i--)//这里操作和上面差不多
{
A.push_back(a[i] - '0');
}
int r;
C = div(A, b,r);
for (int i = C.size()-1; i >= 0; i--)
{
cout << C[i];
}
cout << endl;
cout << r;
return 0;
}
五 练习
a-b
这里直接用上面的代码就行
#include <iostream>
#include <vector>
using namespace std;
bool cmp(vector<int>& A, vector<int>& B)//比较函数
{
if (A.size() != B.size())
return A.size() > B.size();
for (int i = A.size() - 1; i >= 0; i--)
{
if (A[i] != B[i])
return A[i] > B[i];
}
return true;
}
vector<int> sub(vector<int>& A, vector<int>& B)//减法函数
{
int t = 0;
vector<int>C;
for (int 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,说明没有借位,如果小于0,就借位了
//这里+10是先算它进位,然后再%10,如果没有进位,那就是它本身
//如果进位了,那我们插入的就是10-t;
if (t < 0) t = 1;//借位等于1,下次循环,A[i]就需要-1
else t = 0;
}
while (C.size() > 1 && C.back() == 0)C.pop_back();//这里需要去掉前导零
return C;
}
int main()
{
string a, b;
vector<int>A, B, C;
cin >> 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)) C = sub(A, B);//这是判断大小
else C = sub(B, A), cout << '-';//如果A小于B,那么我们可以换成-(B-A)
//这里要多输出一个符号
for (int i = C.size()-1; i >= 0; i--)
{
cout << C[i];
}
cout << endl;
return 0;
}
a+b
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e6 + 10;
vector<int>add(vector<int>& A, vector<int>& B)
{
vector<int>C;
int t = 0;
for (int i = 0; i < A.size() || i < B.size(); i++)
{
if (i < A.size()) t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t)
C.push_back(1);
return C;
}
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');
vector<int>C;
C = add(A, B);
for (int i = C.size() - 1; i >= 0; i--)
{
cout << C[i];
}
return 0;
}
六 总结
以上高精度算法,加法和乘法比较简单,除法和减法需要一点细节理解
加法没有去前导零的操作,其他都有,以上就是高精度的全部内容了,希望对你有所帮助