高精度计算
高精度计算
当我们计算天文数字时,int 就不够用了(-2147483648~2147483647)(10位),long long 有时也不够用(-9223372036854775808~9223372036854775807)(20位)
而高精度计算就是来解决这类问题
问题:现有数据类型无法存储20位以上的数字,我们就用到数组存储,要选择正序还是倒序呢?
如果选择正序,例如a[0] 为最高位,a[1] 为次高位,等到我们进位时,就没法存储了。
因为数组是可以往后延伸,所以我们使用倒序存储
void in() { memset(a,0,sizeof(a));//初始化 cin>>str1; //一次输入字符串 a[0]=str1.length();//a[0]空缺,减少变量,存长度 for(i=1;i<=a[0];i++) a[i]=str1[a[0]-i]-'0';//字符转int }
存储的问题解决了,那么如何进行运算呢?
模拟大法好
加法:对应位相加,满10进1
减法:比较被减数与减数,确定答案正负号,大减小
乘法:两个数的每一位与每一位相乘,累计到i+j-1位,满10进1
加法
 
#include<iostream> #include<cstring> #define N 10010 using namespace std; string str1,str2; int a[N],b[N],len,i; void in() { memset(a,0,sizeof(a)); //初始化 memset(b,0,sizeof(b)); cin>>str1>>str2; a[0]=str1.length(); //在a数组中只用了1-....用a[0]存长度减少变量 b[0]=str2.length(); for(i=1;i<=a[0];i++) a[i]=str1[a[0]-i]-'0'; //字符串转数组,运算 for(i=1;i<=b[0];i++) b[i]=str2[b[0]-i]-'0'; //倒序存储,方便进位 } void add() { len=(a[0]>b[0]?a[0]:b[0]); //三目运算符 for(i=1;i<=len;i++) { a[i]+=b[i]; //对应位置相加 a[i+1]+=a[i]/10; //进位 a[i]%=10; } len++; //防止最高位进位 } void out() { while((a[len]==0)&&(len>1)) len--; //去前导零,防止最高位为零 for(i=len;i>=1;i--) cout<<a[i]; } int main() { in(); add(); out(); }
减法
 
#include<iostream> #include<cstring> #define N 100000 using namespace std; string str1,str2; int a[N],b[N],len,i; int compare(string s1,string s2) //判断两数大小 { if(s1.length()>s2.length()) return 0; //先比长度 if(s1.length()<s2.length()) return 1; for(int i=0;i<=s1.length();i++) //再从最高位开始判断 { if(s1[i]>s2[i]) return 0; if(s1[i]<s2[i]) return 1; } return 0; //如果一样返回零 } void in() { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); cin>>str1>>str2; a[0]=str1.length(); b[0]=str2.length(); for(i=1;i<=a[0];i++) a[i]=str1[a[0]-i]-'0'; for(i=1;i<=b[0];i++) b[i]=str2[b[0]-i]-'0'; } void sub() { if((compare(str1,str2))==0)//s1>s2,结果为正 { for(i=1;i<=a[0];i++) { a[i]-=b[i];//对应位相减 if(a[i]<0)//借位 {a[i+1]--;a[i]+=10;} } a[0]++;//防止进位 while((a[a[0]]==0)&&(a[0]>1)) a[0]--;//去前导零 for(i=a[0];i>=1;i--) cout<<a[i]; cout<<endl; } else { cout<<'-';//s1<s2,答案为负 for(i=1;i<=b[0];i++) { b[i]-=a[i]; if(b[i]<0) {b[i+1]--;b[i]+=10;} } b[0]++; while((b[b[0]]==0)&&(b[0]>1)) b[0]--; for(i=b[0];i>=1;i--) cout<<b[i]; cout<<endl; } } int main() { in(); sub(); }
 
#include<iostream> #include<cstring> #define N 1000000 using namespace std; string str1,str2; int a[N],b[N],c[N],len; int i,j; void in() { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); cin>>str1>>str2; a[0]=str1.length(); b[0]=str2.length(); for(i=1;i<=a[0];i++) a[i]=str1[a[0]-i]-'0'; for(i=1;i<=b[0];i++) b[i]=str2[b[0]-i]-'0'; } void mul() { for(i=1;i<=a[0];i++) for(j=1;j<=b[0];j++) { c[i+j-1]+=a[i]*b[j];//对应位相乘 c[i+j]+=c[i+j-1]/10;//进位 c[i+j-1]%=10; } } void out() { len=a[0]+b[0]+1; while((c[len]==0)&&(len>1)) len--; for(i=len;i>=1;i--) cout<<c[i]; } int main() { in(); mul(); out(); }
 
#include<iostream> #include<cstdio> #include<cstring> #define N 100100 using namespace std; char s[N]; int a[N],b; int main() { int la,b; cin>>s>>b; la=strlen(s); for (int i=1;i<=la;i++) a[i]=s[la-i]-48; int d,r=0; for (int i=la;i>=1;i--) { d=r*10+a[i]; a[i]=d/b; r=d%b; } while(a[la]==0) la--;//处理最高位 for(int i=la;i>=1;i--) cout<<a[i]; cout<<endl; }
2^n
 
#include<iostream> #include<cstring> #define N 50 using namespace std; int a[N],n,lena=1; int main() { cin>>n; a[0]=1; while(n--) { for(int i=0;i<lena;i++)a[i]*=2; for(int i=0;i<lena;i++) { if(a[i]>9) { a[i+1]++; a[i]-=10; if(i==lena-1)lena++; } } } for(int i=lena-1;i>=0;i--)cout<<a[i]; cout<<endl; }
 
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; int a[40000]={1},ans[40000]={1}; int b,t,la=1,lans=1; void jiecheng(int j) { b=0; for(int k=0;k<la;k++) { t=a[k]*j+b; b=t/10; a[k]=t%10; } while(b>0) { a[la++]+=b%10; b/=10; } } void add() { int x=0; lans=lans>la?lans:la; for(int i=0;i<lans;i++) { ans[i]=ans[i]+a[i]+x; x=ans[i]/10; ans[i]%=10; } if(x>0) { ans[lans++]=x; } } int main() { int n; cin>>n; for(int i=2;i<=n;i++)//先算阶乘后相加 { jiecheng(i); add(); } while(ans[lans]==0)//去前导零 { lans--; } for(int i=lans;i>=0;i--) { cout<<ans[i]; } return 0; }
 
#include<iostream> #include<cstring> #define N 100010 using namespace std; int n,a[N],lena=1; int main() { cin>>n; a[0]=1; for(int k=2;k<=n;k++) { for(int i=0;i<lena;i++) a[i]*=k; for(int i=0;i<lena;i++) { if(a[i]>9) { a[i+1]+=a[i]/10; a[i]%=10; if(i==lena-1)lena++; } } } for(int i=lena-1;i>=0;i--)cout<<a[i]; cout<<endl; }
重载运算符
 
#include <cstdio> #include <string> #include<iostream> #include<algorithm> #include<cstring> #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; struct Data { int a[100001],len;//存储每位数的数组和长度 Data()//初始值 { memset(a, 0, sizeof(a)); len = 1; } void read()//读入函数 { char d[100001]; scanf("%s",d); int l=strlen(d); for(int i=1; i<=l; i++) a[i]=d[l-i]-'0';//倒序存储,方便进位 len=l;//记录长度 } void write()//输出函数 { for(int i = len; i>=1; i--) printf("%d", a[i]);//倒序输出 } void clean()//去掉前导零 { while (len>1&&!a[len]) len--; } friend bool operator < (const Data &A,const Data & B) //可以定义在外,外面请不要加friend;在内部不加friend,不能用两个参数 {//const防止你改值,别忘了取地址 & if(A.len>B.len) return 0; //先比长度 if(A.len<B.len) return 1; for(int i=1;i<=A.len;i++) //再从最高位开始判断 { if(A.a[i]>B.a[i]) return 0; if(A.a[i]<B.a[i]) return 1; } return 0; //如果一样返回零 } friend bool operator <= (const Data & A,const Data & B) { if(A.len>B.len) return 0; if(A.len<B.len) return 1; for(int i=1;i<=A.len;i++) { if(A.a[i]>B.a[i]) return 0; if(A.a[i]<B.a[i]) return 1; } return 1; //如果一样返回 1 } friend bool operator > (const Data & A,const Data & B) { if(A.len>B.len) return 1; if(A.len<B.len) return 0; for(int i=1;i<=A.len;i++) { if(A.a[i]>B.a[i]) return 1; if(A.a[i]<B.a[i]) return 0; } return 0; } friend bool operator >= (const Data & A,const Data &B) { if(A.len>B.len) return 1; if(A.len<B.len) return 0; for(int i=1;i<=A.len;i++) { if(A.a[i]>B.a[i]) return 1; if(A.a[i]<B.a[i]) return 0; } return 1; } friend bool operator == (const Data & A,const Data &B) { if(A.len>B.len) return 0; if(A.len<B.len) return 0; for(int i=1;i<=A.len;i++) { if(A.a[i]>B.a[i]) return 0; if(A.a[i]<B.a[i]) return 0; } return 1;//长度相等,对应位数相等才相等 } friend Data operator + (const Data &A,const Data &B) { Data C;//因为A,B均不可以改值,所以引入C,C长度1,值为0 C.len = max(B.len, A.len);//选取A,B长度最大的 for(int i = 1 ; i <= C.len; i++)//边界需要注意 { C.a[i] += A.a[i]+B.a[i];//对应位相加 if(C.a[i] >= 10)//每十进一 { C.a[i] -= 10; //由于不会超过10,故用 -=10 代替 %10 效率更高 C.a[i+1]++;//进位 } } if(C.a[C.len+1])//考虑是否会进到B.len的下一位 C.len++; C.clean();//去0,即使长度大了也不要紧 return C; } friend Data operator - (const Data &A ,const Data &B) { Data C;//因为A,B均不可以改值,所以引入C,C长度1,值为0 if( A > B) { C.len=A.len; for(int i=1;i<=A.len;i++) { C.a[i]+=A.a[i]-B.a[i]; if(C.a[i]<0)//借位 {C.a[i+1]--;C.a[i]+=10;} } if(C.a[C.len+1]) C.len++; C.clean(); return C; } else if(A==B)//防止出现1-1=-0的情况 { return C;//C的初始长度为1,值为0 } else if (A<B) { cout<<'-'; C.len=B.len; for(int i=1;i<=B.len;i++) { C.a[i]+=B.a[i]-A.a[i]; if(C.a[i]<0) {C.a[i+1]--;C.a[i]+=10;} } if(C.a[C.len+1]) C.len++; C.clean(); return C; } } friend Data operator * (const Data &A ,const Data &B) { Data C; C.len=A.len+B.len; //C的长度最大为 A.len+B.len,有时 A.len+B.len-1 for(int i=1;i<=A.len;i++) for(int j=1;j<=B.len;j++) { C.a[i+j-1]+=A.a[i]*B.a[j]; //相乘结果加在i+j-1上 C.a[i+j]+=C.a[i+j-1]/10; C.a[i+j-1]%=10; } if(C.a[C.len+1]) C.len++; C.clean(); return C; } }; Data A,B,C; int main() { A.read(); B.read(); C = A+B; //C=A-B; //C=A*B; C.write(); return 0; }
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号