填坑行动1-高精度运算
Update8.12:更改了一些错误的地方
前置芝士-运算符重载
例子
看下边的代码:
#inclue<iostream> using namespace std; int main(){ int a,b; cin>>a>>b; cout<<a+b; }
cin>>a>>b
在这里是指输入两个数 ,就有人会问了,>>
不是右移吗?怎么用来输入变量了?其实这就是一个简单的运算符重载。
方法
那么我们改怎么重载呢?
类型 operator 符号(参数) const { 内容(记得带返回值) }
其中const
是要在结构体里面定义的时候才加。
可以重载的符号有:
new delete new[] delete[] + - * / % ^ & & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> () []
其中[]
指下标,
可以有两个参数,也可以有一个参数的有:
+ - * &
当然,重载流输流输出有不一样的格式,这是友元函数:
friend istream & operator >> (istream &,bigint &x){ ... return cin; } friend ostream & operator <<(ostream &,bigint x){ ... return cout; }
高精度运算
存储
有些时候进行运算的时候,数字会很大,导致int_128
都装不下,不如自己动手,丰衣足食,自己定义一种变量,满足进行很大的数字的运算。这里叫bigint
那么,bigint
里面要有什么东西呢?我们先看一下short
是怎么存贮的:主要是int有32位画不下
我们就可以定义一个数组,数组的每一位,代表每一个数。还有两个变量,一个代表长度,一个代表正负,就是这样:
struct bigint{ int len,flag;//flag 1 fu 0 zheng int a[maxn]; }
输入输出&&运算原理
然后考虑怎么运算,其实很简单,就像小学生一样做竖式运算就可以了,为了方便进行运算,令为个位,为十位,为百位,以此类推即可。
然后考虑怎么输入,我们发现,输入的是一个很大的数字,不能直接用cin
,为了一次性读入,我们读入一个字符串,不难得到,最后删去前导零,比如说要写成
输出只要倒着输出就可以了。一个for循环搞定。记得注意符号。
奉上输入输出重载:
friend istream & operator >> (istream &,bigint &x){ char s[maxn]; cin>>s; x.len=strlen(s); if(s[0]=='-') x.flag=1; memset(x.a,0,sizeof(x.a)); if(x.flag) for(register int i=1;i<x.len;i++) x.a[i]=s[x.len-i]^48; else for(register int i=1;i<=x.len;i++) x.a[i]=s[x.len-i]^48; for(;x.len>1;x.len--) if(x.a[x.len]!=0) break;//删去前导零 return cin; } friend ostream & operator <<(ostream & ,bigint x){ if(x.flag) printf("-"); int flag=0; for(register int i=x.len;i>=1;i--){ if(x.a[i]>0) flag=1; if(flag) printf("%d",x.a[i]); } if(!flag) putchar('0'); return cout; }
加减
加减只要按照竖式法从低到高加就可以了,还要注意进位,算法复杂度
注意正负就可以了。(初中老师应该讲过有理数的加减的吧)
乘除
乘法依旧是竖式计算,不过正负的处理更加简单。
注意的结果应该储存在中,注意ans.len=a.len+b.len-1
或者ans.len=a.len+b.len
除法也可以用竖式解决,这里暂时不涉及。
代码
最后献上代码。据说很多人喜欢这个
struct bigint{ int len,flag;//flag 1 fu 0 zheng int a[maxn]; bigint (*intit)(int); void (*check)(bigint); friend istream & operator >> (istream &,bigint &x){ char s[maxn]; cin>>s; x.len=strlen(s); if(s[0]=='-') x.flag=1; memset(x.a,0,sizeof(x.a)); if(x.flag) for(register int i=1;i<x.len;i++) x.a[i]=s[x.len-i]^48; else for(register int i=1;i<=x.len;i++) x.a[i]=s[x.len-i]^48; for(;x.len>1;x.len--) if(x.a[x.len]!=0) break;//ɾȥǰµ¼Áã return cin; } friend ostream & operator <<(ostream & ,bigint x){ if(x.flag) printf("-"); int flag=0; for(register int i=x.len;i>=1;i--){ if(x.a[i]>0) flag=1; if(flag) printf("%d",x.a[i]); } if(!flag) putchar('0'); return cout; } bool operator > (const bigint &x)const{ if(!x.flag&&!this->flag){ if(this->len > x.len ) return true; if(this->len < x.len ) return false; for(int i=x.len;i>=1;i--) if( this->a[i] > x.a[i] ) return true; else if( this->a[i] < x.a[i] ) return false; } if(this->flag&&!x.flag) return false; if(!this->flag&&x.flag) return true; if(this->len < x.len ) return true; if(this->len > x.len ) return false; for(int i=x.len;i>=1;i--) if( this->a[i] < x.a[i] ) return true; else if( this->a[i] > x.a[i] ) return false; return false; } bool operator == (const bigint &x)const{ if(x.flag!=this->flag) return 0; for(int i=1;i<=max(x.len,this->len);i++) if(x.a[i]!=this->a[i]) return 0; return 1; } bool operator < (const bigint &x) const { return !(*this>=x); } bool operator <= (const bigint &x) const { return !(*this>x); } bool operator >= (const bigint &x) const { return *this>x || *this==x;} bigint operator +(const bigint &x) const { bigint ans=(bigint){0,0,{}}; int jw=0; if(this->flag==x.flag){ ans.flag=x.flag; ans.len=max(this->len,x.len); for(int i=1;i<=ans.len;i++) if(this->a[i]+x.a[i]+jw>=10){ ans.a[i]=(this->a[i]+x.a[i]+jw)-10; jw=1; } else{ ans.a[i]=(this->a[i]+x.a[i]+jw); jw=0; } if(jw==1){ ans.len++; ans.a[ans.len]=1; } return ans; } bigint thi; int flag,tw; if(this->flag==1&&x.flag==0){ memset(thi.a,0,sizeof(thi.a)); for(int i=1;i<=x.len;i++) thi.a[i]=this->a[i]; thi.flag=0; thi.len=this->len; if(thi>x){ ans.flag=1; for(int i=1;i<=thi.len;i++) if(thi.a[i]-tw-x.a[i]<0){ ans.a[i]=thi.a[i]-tw-x.a[i]+10; tw=1; } else{ ans.a[i]=thi.a[i]-tw-x.a[i]; tw=0; } ans.len=thi.len; } else{ ans.flag=0; for(int i=1;i<=x.len;i++) if(x.a[i]-tw-thi.a[i]<0){ ans.a[i]=x.a[i]-tw-thi.a[i]+10; tw=1; } else{ ans.a[i]=x.a[i]-tw-thi.a[i]; tw=0; } ans.len=x.len; } } if(this->flag==0&&x.flag==1){ memset(thi.a,0,sizeof(thi)); for(int i=1;i<=x.len;i++) thi.a[i]=x.a[i]; thi.flag=0; thi.len=x.len; if(*this>=thi){ ans.flag=0; ans.len=this->len; for(int i=1;i<=ans.len;i++) if(this->a[i]-tw-thi.a[i]<0){ ans.a[i]=this->a[i]-tw-thi.a[i]+10; tw=1; } else{ ans.a[i]=this->a[i]-tw-thi.a[i]; tw=0; } } else{ ans.flag=1; ans.len=thi.len; for(int i=1;i<=ans.len;i++) if(thi.a[i]-tw-this->a[i]<0){ ans.a[i]=thi.a[i]-tw-this->a[i]+10; tw=1; } else{ ans.a[i]=thi.a[i]-tw-this->a[i]; tw=0; } } } while(ans.len>1&&ans.a[ans.len]==1) ans.len--; return ans; } bigint operator -(const bigint &x) const { bigint thi; memset(thi.a,0,sizeof(thi.a)); thi.len=x.len; for(int i=1;i<=x.len;i++) thi.a[i]=x.a[i]; thi.flag=!x.flag; return *this+thi; } bigint operator *(bigint &x){ bigint ans=(bigint){0,0,{0}}; for(register int i=1;i<=x.len;i++) for(register int j=1;j<=this->len;j++){ ans.a[i+j-1]+=this->a[j]*x.a[i]; ans.a[i+j]+=ans.a[i+j-1]/10; ans.a[i+j-1]%=10; } ans.len=this->len+x.len+1; ans.flag=(this->flag)^(x.flag); while(ans.a[ans.len]==0&&ans.len>1) ans.len--; return ans; } }; bigint intit(int x){ bigint ans=(bigint){0,0,{0}}; if(x<0){ x=-x; ans.flag=1; } if(x==0){ ans.len=1; return ans; } while(x>0){ ans.a[++ans.len]=x%10; x/=10; } return ans; }
记得定义maxn
的大小哦~~~(maxn
是位数)
这里重载了 >> << + - * > < >= <= ==
bigint init(int)
是把一个int类型的数转化成bigint类型。
完结撒花
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具