由于c++/c语言特性,当数很大时,就要考虑精度问题,python和java则不用,因此c++学会精度运算很重要的,这里作个总结
1.高精度加法
给定两个正整数(不含前导 0),计算它们的和。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的和。
数据范围
1≤整数长度≤100000
输入样例:
12
23
输出样例:
35
思路:,这么大的数字用int,long long之类的肯定不好处理,但如果把一个很大数字的每一位存进一个数组里,那就很好的解决这个问题,这里用vector存储避免数组开太大,多的用不到。
存入一个数组之后两个数组就是每一位相加,大于10就进位,和小学时学的数学相加一样,不废话直接出代码
代码实现:
#include<iostream>
#include<vector>
using namespace std;
//计算C
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);//c的值就是进位的个位数
t/=10;把t的个位数去掉只剩下十位数,即只剩下这个位置的进位
}
if(t) C.push_back(1);//如果t==1,表示还有一个进位,要补上
return C;
}
int main()
{
string a,b;//由于数字可能很长,用string存储
cin>>a>>b;
vector<int> A,B;
//A和B倒着放进int数组,因为有进位,倒着放容易处理
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];
cout<<endl;
return 0;
}
2.高精度减法
给定两个正整数(不含前导 0),计算它们的差,计算结果可能为负数。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的差。
数据范围
1≤整数长度≤105
输入样例:
32
11
输出样例:
21
思路:和高精度加法一样,这里一样用了我们小学学的减法的公式,每一位与每一位对应相减,不够就要往高位借位,如果被减的数比减它的数更大,此时可以变成-(被减的数-原本该减它的数),比如我要求4-9,此时需要输出-5,可以看成-(9-4),保证里面大数减去小数,我们的代码就更容易实现
代码实现:
#include<iostream>
#include<vector>
using namespace std;
//判断A和B的长度哪个大
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)//这里通过前面的判断,进来的A长度必然>=B的长度
{
vector<int> C;
int t=0;
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);
if(t<0) t=1;
else t=0;
}
while(C.size()>1&&C.back()==0) C.pop_back();//这步操作是为了去除前面的0,比如600-599=001,前面的两个0要去掉
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;
if(cmp(A,B)) C=sub(A,B);
else C=sub(B,A),cout<<"-";
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
cout<<endl;
return 0;
}
3.高精度乘法
给定两个非负整数(不含前导 0) A 和 B,请你计算 A×B 的值。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共一行,包含 A×B 的值。
数据范围
1≤A的长度≤100000,
0≤B≤10000
输入样例:
2
3
输出样例:
6
思路:仍然是用小学我们学数学的乘法思路进行计算,由于这里是一个很大的数和一个小数相乘,因此就是把大数存入数组,从个位开始每个元素乘以 该小数b,留下模10后的数,进除以10后的数,这里直接放代码更好理解。(两个大数相乘稍微改一下思路就行,这题是大数乘小数)
代码实现:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> xiaochou(vector<int>&A,int b)
{
vector<int> C;
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);//把每个位置相乘后的数模10存进C中
t/=10;//除10,进位
}
while(C.size()>1&&C.back()==0) C.pop_back();//假如相乘为0,比如26乘0的话就会等于00,
//应当去除掉多余的0只保留一个
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=xiaochou(A,b);
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
cout<<endl;
return 0;
}
4.高精度除法
给定两个非负整数(不含前导 0) A,B,请你计算 A/B 的商和余数。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共两行,第一行输出所求的商,第二行输出所求余数。
数据范围
1≤A的长度≤100000,
1≤B≤10000,
B 一定不为 0
输入样例:
7
2
输出样例:
3
1
思路:同样是小学我们学除法的思路,如图所示
代码实现也不难,这里直接给出来了
代码实现:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> xiaochou(vector<int>&A,int b,int& r)//这里要注意r要传入指针,r改变主函数的r也改变
{
vector<int> C;
for(int i=A.size()-1;i>=0;i--)
{
r=r*10+A[i];//(前一位的余数*10+当前该数)即是此时应当被b除的数
C.push_back(r/b);
r%=b;
}
reverse(C.begin(),C.end());//这里翻转是为了更好的出去无用的前导0
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=xiaochou(A,b,r);
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
printf("\n%d\n",r);
return 0;
}
注意:这里可能有人会疑惑为什么还要倒序存入A中,这里正常来讲由于除法的特性其实不倒叙更好,但是由于一般的题目中不可能只考一个除法(由前面知道加减乘都是倒序存储),因此我们统一给他倒序存入,方便其他操作(如加减乘)