一、高精度运算基本原理
高精度运算也称之为大数运算。即:在变量运算对象的数值范围为任何数据类型所无法容纳的情况下,采用整数数组存储(用字符串表示数字)。高精度运算的难度并不大,考虑不清楚的话列个竖式模拟计算一下即可。
高精度运算的基本思路如下:
- 将输入的字符串按位转为int格式存储到容器或是数组中;
- 通过循环对每一位做运算处理,注意是否有进位或是借位等情况;
- 考虑循环终止后的边界情况,按位输出即可。
二、 高精度加法
题目描述
给定两个正整数(不含前导 00),计算它们的和。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的和。
数据范围
1 ≤ 整数长度 ≤ 100000
输入样例:
12 23
输出样例:
35
题目链接:
参考代码如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string A,B;
//这里我图方便用vector容器来存储数据,一般情况下数组会快一点
vector<int> a,b,c;
cin>>A>>B;
int i,temp = 0;
//逆向存储,A[0]是最低位
for(i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
for(i=0;i<a.size()||i<b.size();i++)
{
if(i<a.size()) temp += a[i];
if(i<b.size()) temp += b[i];
c.push_back(temp%10);
temp /= 10;//进位
}
if(temp) c.push_back(1);//如果最后还有进位的话
for(i=c.size()-1;i>=0;i--)
printf("%d",c[i]);
return 0;
}
三、高精度减法
题目描述
给定两个正整数(不含前导 00),计算它们的差,计算结果可能为负数。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的差。
数据范围
1 ≤ 整数长度 ≤ 100000
输入样例:
32 11
输出样例:
21
题目链接:
减法需要比加法多考虑一个正负的问题,如果A>B,正常计算,如果A<B的话,答案需要加个负号,参考代码如下:
#include<bits/stdc++.h>
using namespace std;
//判断是否A>=B
bool cmp(vector<int> a,vector<int> b)
{
//先比较A和B的长度
if(a.size() != b.size())
return a.size()>b.size();
//A和B长度相等时,逐位比大小
for(int i=a.size()-1;i>=0;i--)
if(a[i] != b[i]) return a[i]>b[i];
return true;
}
//除法运算,A-B
void sub(vector<int> a,vector<int> b,vector<int>& c)
{
int i,temp = 0;
for(i=0;i<a.size()||i<b.size();i++)
{
temp = a[i]-temp;
if(i<b.size()) temp -= b[i];
c.push_back((temp+10)%10);//t<0即不够减,需要加10再模10
if(temp < 0) temp = 1;//借位
else temp = 0;
}
while(c.size()>1 && c.back()==0)
c.pop_back();//注意前面的数都正好减完,为0的情况
}
int main()
{
string A,B;
vector<int> a,b,c;
cin>>A>>B;
int i;
//逆向存储,A[0]是最低位
for(i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
if(cmp(a,b)) sub(a,b,c);
else{
sub(b,a,c);
printf("-");//A<B时需要额外输出负号
}
for(i=c.size()-1;i>=0;i--)
printf("%d",c[i]);
return 0;
}
四、高精度乘法
题目描述
给定两个非负整数(不含前导 0)A 和 B,请你计算 A×B 的值。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共一行,包含 A×B的值。
数据范围
1 ≤ A的长度 ≤ 100000,
0 ≤ B ≤ 100000(注意B的数据范围)输入样例:
2 3
输出样例:
6
题目链接:
乘法不是一位一位计算,而是B去乘以A的每一位,以下为高精度x低精度的参考代码:
#include<bits/stdc++.h>
using namespace std;
void mul(vector<int> a,int B,vector<int>& c)
{
int i,temp = 0;//temp是进位
for(i=0;i<a.size() || temp;i++)//没有处理完a或者进位时,要继续做
{
if(i<a.size()) temp += a[i]*B;
c.push_back(temp%10);//只取个位
temp /= 10;//多余的看作进位
}
while(c.size()>1 && c.back()==0) c.pop_back();//可能有前导零
}
int main()
{
string A;
int B,i;
vector<int> a,c;
cin>>A>>B;
//逆向存储,A[0]是最低位
for(i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
mul(a,B,c);
for(i=c.size()-1;i>=0;i--)
printf("%d",c[i]);
return 0;
}
高精度x高精度的代码模板如下:
#include<bits/stdc++.h>
using namespace std;
void mul(vector<int> a,vector<int> b,vector<int>& c)
{
int i,j,temp = 0;//temp是进位
for(i = 0; i < a.size(); i++)
for(j = 0; j < b.size(); j++)
c[i + j] += a[i] * b[j];
for(i=0;i<c.size() || temp;i++)//没有处理完a或者进位时,要继续做
{
temp += c[i];
c[i] = temp%10;//只取个位
temp /= 10;//多余的看作进位
}
while(c.size()>1 && c.back()==0) c.pop_back();//可能有前导零
}
int main()
{
string A,B;
int i;
vector<int> a,b;
cin>>A>>B;
//逆向存储,A[0]是最低位
for(i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
vector<int> c(a.size()+b.size()+10,0);//初始化为 0,C的size取大一点
mul(a,b,c);
for(i=c.size()-1;i>=0;i--)
printf("%d",c[i]);
return 0;
}
五、高精度除法
题目描述
给定两个非负整数(不含前导 0) A,B,请你计算 A/B的商和余数。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共两行,第一行输出所求的商,第二行输出所求余数。
数据范围
1 ≤ A的长度 ≤ 100000,
1 ≤ B ≤ 10000,
B一定不为 0输入样例:
7 2
输出样例:
3 1
题目链接:
以下为除法(高精度/低精度)的代码模板:
#include<bits/stdc++.h>
using namespace std;
// A/B = C.....r
void div(vector<int> a,int B,vector<int>& c,int &r)
{
int i;
for(i=a.size()-1;i>=0;i--)
{
r = r*10 + a[i];//将上次的余数*10在加上当前位的数字,便是该位需要除的被除数
c.push_back(r/B);//被除数/除数得到的商
r %= B;//当前的余数
}
//由于在除法运算中,高位到低位运算,因此前导零都在vector的前面而不是尾部
//因此我们将c翻转,这样0就位于数组尾部,可以使用pop函数删除前导0
reverse(c.begin(),c.end());
while(c.size()>1 && c.back()==0) c.pop_back();//去除前导零
}
int main()
{
string A;
int B,i,r = 0;//余数要记得初始化
cin>>A>>B;
vector<int> a,c;
//注意之前的加减乘法都是从低位算到高位,而除法是从高位算到低位
//所以这里完全可以按顺序存储,此处为了和之前保持一致,所以仍选择倒序存储
for(i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
div(a,B,c,r);
for(i=c.size()-1;i>=0;i--) printf("%d",c[i]);
cout<<endl<<r<<endl;
return 0;
}