其中高精度的题目不乏就是大数的加减乘除;
说明:其实大部分的处理上,加法用的程度稍微更多一点。减法虽然也用,但是在边界处理,其实就是实现函数上弯弯绕更多了一些
加法(应该是最简单的):过多的说明我就不再去进行补充了,真的是最基本的了。
其实最重要的vector我们实现的加法函数。
一定要注意函数的定义,我就写错了很多次。实在没注意
#include <iostream>
#include <vector>
const int N=1e6+10;
using namespace std;
vector<int> add(vector<int>& A,vector<int>& B){
vector<int> C;
int carry=0;
for(int i=0;i<A.size()||i<B.size();i++){
if(i<A.size()) carry+=A[i];
if(i<B.size()) carry+=B[i];
C.push_back(carry%10);
carry/=10;
}
if(carry) C.push_back(1);
return C;
}
int main(){
string a,b;//123456
vector<int> A,B;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');//6,5,4,3,2,1
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;
}
高精度减法:
#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();
else{
for(int i=A.size()-1;i>=0;i--){
if(A[i]!=B[i]){
return A[i]>B[i];
}
}
}
return true;
}
//一定要搞清楚sub函数的关系
vector<int> sub(vector<int> &A,vector<int> &B){
vector<int> C;
int carry=0;
for(int i=0;i<A.size();i++){
carry=A[i]-carry;
if(i<B.size()) carry-=B[i];
C.push_back((carry+10)%10);//这个其实就是综合两种情况
if(carry<0){//这个表示单独的某一个数位相减小于0
//123-55 ---->显然在各位上3-5肯定是小于0的
carry=1;
}
else carry=0;
}
//但是此时C的位数是大位数,也就是位数=max(A,B)的位数
//比如125-123 ,vectorC的结果是2 0 0 (注意这里的顺序)
//back()函数处理的数字的末尾。
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');
//auto C=cmp(A,B)?sub(A,B):(-sub(B,A)); 千万注意不能这么写,第二章情况处理不了
//我第一次图旁边就是这么写得,但是这样就导致了符号重载。
if(cmp(A,B)) {
auto C=sub(A,B);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
else {
auto C=sub(B,A);
cout<<"-";
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
return 0;
}
高精度的相关题目 | Acwing,pat |
---|---|
高精度加法 | Acwing-791. 高精度加法 |
高精度减法 | Acwing-792. 高精度减法 |
高精度加法+字符串模拟 | pat-1023 Have Fun with Numbers (20分) |
关于pat的那一题的高精度我要去进行说明:long long类型表示的数字范围是10的19次方,显然还是不满足的。而且题目仅仅是对本数字去进行翻倍。与上面的我给的两个模版相比,真的是简单了不少。
题解如下:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
string num;
cin>>num;
vector<int> a;
for(int i=num.size()-1;i>=0;i--) a.push_back(num[i]-'0');//减去一个偏移量,从字符转换一个整数
//怎么翻倍;注意翻倍之后可能位数会相加
vector<int> b;
int t=0;//设置一个进位
for(int i=0;i<a.size();i++){
int sum=a[i]+a[i]+t;
//把当前的位进入进来,而且判断是否大于10(取模就解决了)
b.push_back(sum%10);
t=sum/10;
}
//检查最高位是否还产生了进位,
if(t) b.push_back(t);
//如果判断两个数组中,包含的数是一样的?
vector<int> c=b;
sort(a.begin(),a.end());
sort(c.begin(),c.end());
if(a==c) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
for(int i=b.size()-1;i>=0;i--){
cout<<b[i];
}
return 0;
}
高精度乘法:
题目列举 | leetcode,acwing |
---|---|
大整数乘法 | 43. 字符串相乘 |
大整数乘法 | Acwing-793. 高精度乘法 |
列出我所写出的方法吧。有别于大雪菜的写法。他的写法是一个是大整数,另外一个是稍微小一点的整数。但是我的写法一定是包含他的写法的。
#include <iostream>
using namespace std;
#include <vector>
//分析过程如下
//223
// 9
//-------
//个位:结果的个位:3*9%10=2 进位:carry =3*9/10=2
//十位:结果的十位:(2*9+2)%10=0 进位:carry =(2*9+2)/10=2
//百位:结果的百位:(2*9+2)%10=0 进位:carry =(2*9+2)/10=2
//千位:结果的千位:
//用循环判断
//if(carry) C.push_back(carry)
vector<int> mul(vector<int>& num1,vector<int>& num2){
//大概的长度,默认为若干个0
//使用列表初始化
vector<int> C(num1.size()+num2.size(),0);
for(int i=0;i<num1.size();i++){
for(int j=0;j<num2.size();j++){
int sum=C[i+j]+num1[i]*num2[j];
C[i+j]=sum%10;
C[i+j+1]+=sum/10;//进位
}
}
//取出前导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');
auto c=mul(A,B);
for(int i=c.size()-1;i>=0;i--){
cout<<c[i];
}
return 0;
}
大整数除法: