总结
1.模板中所有的数组全部用vector来实现
2.为了加法方便进位以及统一性,所有的大数字全部都是逆序储存,所有的结果也是逆序储存,除法的商是正序储存的,为了统一性以及末尾去0我们要人为将其变为逆序
3.减法、乘法以及除法的商都是有可能出现前导0的,要注意去除
高精度加法
1.字符串读入两个大数字
2.利用t来存储两个数字每一位相加的结果,其模10后就作为该位上的结果,在对其除10作为下一位的进位位
3.将C数组逆序输出
4.循环次数为两个大数字位数的较大者
#include <iostream>
#include <vector>
using namespace std;
const int N = 100010;
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(t);
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');
auto C = add(A, B);
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
return 0;
}
高精度减法
1.字符串读入两个大数字
2.将两个大数字进行比较,将较大者作为被减数,较小者作为减数,同时判断是否加负号
3.用数字t存储两个数字每一位相减的结果,无论t是否大于0,都将(t + 10) % 10作为该位上的结果,因为如果t小于10是要进行加10借位的,同时模10不会对其产生影响,如果t大于10,10 % 10 = 0,也不会造成影响
4.最后记得去除前导0并逆序输出
5.循环次数为第一个大数字的位数
#include <iostream>
#include <vector>
using namespace std;
bool cmp(string a, string b)
{
if (a.size() != b.size()) return a.size() > b.size();
for (int i = 0; i < a.size(); 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];
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = -1;
else t = 0;
}
while (C.size() != 1 && C.back() == 0) C.pop_back();
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');
if (cmp(a, b))
{
auto C = sub(A, B);
for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
}
else
{
printf("%c", '-');
auto C = sub(B, A);
for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
}
return 0;
}
高精度乘法
1.字符串读入一个大数字
2.与我们熟悉的乘法竖式不同,我们用t存储整个小数字b(而不是其中的一位)与大数字的一位相乘的结果,接着t % 10取走最后一位数字作为该位结果,再t / 10舍弃最后一位数,将剩余的数保留与下一位相乘的结果相加
3.注意乘法如果较小的数字为0的话也会产生前导0,所以要进行特判
4.逆序输出
注意循环次数为i < A.size() || t
,因为该算法每次只能上一位,最后结果很可能位数比大数字要多,所以还需要保证t为0才能结束循环
#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
if (b == 0)
{
C.push_back(0);
return C;
}
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
return C;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
auto C = mul(A, b);
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
return 0;
}
高精度除法
1.用字符串读入被除数大数字
2.除法思路与一般竖式相似,用t存储大数字的每一位与整个小数字相除的结果,将其直接作为该位结果,同时将其对小数字取模的结果保留,将其乘10后与大数字的下一位相加进行循环操作
3.将最后得到的结果进行逆序并去除前导零
4.逆序输出结果
5.注意循环次数为大数字的位数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> div(vector<int> &A, int b, int &r)
{
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());
while (C.size() != 1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
int r = 0;
auto C = div(A, b, r);
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
cout << endl << r << endl;
return 0;
}