高精度算法总结(已完结)
高精度是一种计算方式,如果数据过大,会爆掉longlong,就需要用数组来模拟每一位,进行加减乘除,模拟进退位。
用高精时,要将个位赋值在数组第一个,输出时反向输出,不要弄反,不然会紊乱;
高精加
多考虑进位,这是重点;
#include<iostream> #include<cstring> using namespace std; int x=0,a1[241],a2[241],b[241],o; string s1,s2; void ax() { cin>>s1>>s2;//输入字符串 a1[0]=s1.length();//长度 for(int i=1;i<=a1[0];i++) a1[i]=s1[a1[0]-i]-48;//ASCII码值 转化 a2[0]=s2.length();//长度 for(int i=1;i<=a2[0];i++) a2[i]=s2[a2[0]-i]-48; } //习惯上从一开始循环,所以把个位赋值到1上,输出时反过来 void as(int a1[],int a2[]) { int i=1; while((i<=a1[0])&&(i<=a2[0])) { b[i]=a1[i]+a2[i]+x;//x是进位 x=b[i]/10;//计算进位 b[i]%=10; i++; } if(x!=0) b[i]=x; else i--; o=i; } int main() { ax(); as(a1,a2); for(int j=o;j>=1;j--) cout<<b[j];//反向输出 }
高精减
借位借位啊
要注意 减完之后高位可能会有0,输出前要去掉
#include<iostream> #include<cstring> using namespace std; int a1[241],a2[241],b[241],o,n; string s1,s2; bool ad(int a1[],int a2[])//判断哪个大,用来当被减数 { n=1; if(a1[0]<a2[0]) n=0; if((a1[0]==a2[0])&&(s1<s2)) n=0; return n; } void ax()//输入,赋值,反向赋值 { cin>>s1>>s2; a1[0]=s1.length(); for(int i=1;i<=a1[0];i++) a1[i]=s1[a1[0]-i]-48; a2[0]=s2.length(); for(int i=1;i<=a2[0];i++) a2[i]=s2[a2[0]-i]-48; } void as(int a1[],int a2[])//减 { int i=1; while(i<=a1[0]) { if(a1[i]<a2[i]) { b[i]=a1[i]+10-a2[i]; a1[i+1]--;//借位 } else { b[i]=a1[i]-a2[i]; } i++; } while((b[i]==0)&&(i>1)) i--;//减完之后,前面有可能有0,要去掉后再输出 o=i; } int main() { ax(); if(ad(a1,a2)==1) as(a1,a2); else { as(a2,a1); cout<<"-"; } for(int j=o;j>=1;j--) cout<<b[j]; }
高精乘
同高精加,只不过这回进位要大一点了
乘到哪一位
比如100*100=10000
最高位相乘的个位是i+j-1
再多出来的十位,算到进位中。
#include<iostream> #include<cstring> using namespace std; int x=0,a1[1001],a2[1001],b[1000001],o=0; string s1,s2; void ax()//输入 { cin>>s1>>s2; a1[0]=s1.length(); for(int i=1;i<=a1[0];i++) a1[i]=s1[a1[0]-i]-48; a2[0]=s2.length(); for(int i=1;i<=a2[0];i++) a2[i]=s2[a2[0]-i]-48; } void as(int a1[],int a2[]) { for(int i=1;i<=a1[0];i++)//因为乘法每一位都要相乘 { for(int j=1;j<=a2[0];j++)//所以两层循环 { b[i+j-1]+=a1[i]*a2[j]+x;//相乘 x=b[i+j-1]/10;//进位 b[i+j-1]%=10;//余下的 o=i+j-1;//总位数 } if(x!=0) { b[o+1]=b[o+1]+x; x=0; o=o+1; } } } int main() { ax(); as(a1,a2); for(int j=o;j>=1;j--) cout<<b[j]; }
高精除
经过我的悉心研究;
已经成功的搞出了高精除的算法代码
算法:
其实直接实现除法是不可能的,可以用减法来代替实现
按照除数的长度,由被除数的最高位减去这个长度,依次循环;
每一次都循环减去除数,当减到不能再减的时候,输出这个次数,就是这一位的商;
依次循环,可以得解
记住这里面有一些细节,注意减位的错误;;
在打代码的时候你会发现这个问题的
加油,高精除相比加减乘,难度上升了好多
下面,粘上代码
#include<bits/stdc++.h> using namespace std; string a,b; int sa[215],sb[215],sum[215]; int camp(int x[],int x1,int y[]) { for(int i=x1+y[0]-1;i>=x1;i--) if(x[i]<y[i-x1+1]) return 0; else if (x[i]>y[i-x1+1]) return 1; return 2; } int jian1(int x1,int x2) { int p=0,x[215]={}; while(p>=0) { if(camp(sa,x1,sb)==0&&sa[x1+x2]==0) break; p++; for(int i=x1;i<=x1+x2-1;i++) { if(sa[i]<sb[i-x1+1]) { x[i]=sa[i]+10-sb[i-x1+1]; sa[i+1]-=1; continue; } else { x[i]=sa[i]-sb[i-x1+1]; continue; } } for(int i=x1;i<=x1+x2-1;i++) { sa[i]=x[i]; } } return p; } int jian2(int x1,int x2) { int p=0,x[215]={}; while(p>=0) { if(camp(sa,x1,sb)==0&&sa[x1+x2-1]==0) break; p++; for(int i=x1;i<=x1+x2-1;i++) { if(sa[i]<sb[i-x1+1]) { x[i]=sa[i]+10-sb[i-x1+1]; sa[i+1]-=1; continue; } else { x[i]=sa[i]-sb[i-x1+1]; continue; } } for(int i=x1;i<=x1+x2-1;i++) { sa[i]=x[i]; } } return p; } int main() { cin>>a>>b; sa[0]=a.length(); sb[0]=b.length(); for(int i=1;i<=sa[0];i++) sa[i]=a[sa[0]-i]-48; for(int i=1;i<=sb[0];i++) sb[i]=b[sb[0]-i]-48; for(int i=sa[0]-sb[0]+1;i>=1;i--) { if(sa[i+sb[0]]!=0) { sum[i]=jian2(i,sb[0]+1); continue; } if(camp(sa,i,sb)==2) { //cout<<"1"<<endl; sum[i]=1; for(int j=i;j<=i+sb[0]-1;j++) sa[j]=0; continue; } if(camp(sa,i,sb)==1) { sum[i]=jian1(i,sb[0]); continue; } if(camp(sa,i,sb)==0) { sum[i]=0; continue; } } int nn=sa[0]; while(sum[nn]==0)nn--; //cout<<nn<<endl; for(int i=nn;i>=1;i--) cout<<sum[i]; }
QQ:2953174821