大数运算教程 c++

由于c++的内置整型一般最大为long long,只能保存2^63次方的整数,在很多时候需求量较大时可能会发生溢出等现象

所以大数类便应运而生

1 class bigNum{
4     private:
5         int a[maxn],len;
6         char sign;
7 };

 

在此分享一下大数算法

大数加法:

通过我们从小到大进行的各种加法运算,发现列竖式这样的方法十分符合计算机执行力强大的特征,而且又较好实现,废话8说,看图

因此,只需要将对应位相加,如果有进位的话,可置一个flag,用于表达是否进位

为了方便运算,可以先用string存储数据,然后将之倒过来放进int 数组里。

这是大数类的构造函数和赋值函数

 1 bigNum():len(0){memset(a,0,sizeof(a));};
 2 bigNum(string s){change(s);};
 3 bigNum(int n){change(to_string(n));};
 4 void change(string s)
 5 {
 6     if(s[0]=='-'){
 7         sign='-';
 8         s.erase(s.begin());
 9     }
10     else sign='+';
11     len=s.size();
12     for(int i=len-1;i>=0;--i) a[len-1-i]=s[i]-'0';//将数组颠倒,便于计算
13 }

 

代码如下:

 1 bigNum add(const bigNum &rhs)const
 2 {
 3     bigNum ans;//返回的对象
 4     memset(ans.a,0,sizeof(ans.a));//清零很重要,否则易出现很多错误
 5     int mlen=max(this->len,rhs.len),flag=0;//flag
 6     for(int i=0;i<mlen;++i){
 7         ans.a[i]=this->a[i]+rhs.a[i]+flag;
 8         flag=0;
 9         flag=ans.a[i]/10;
10         ans.a[i]%=10;
11     }
12     if(flag) ans.a[mlen++]=1;
13     ans.len=mlen;
14     return ans;
15 }

 

同理,对于减法,也是用列竖式的方法

代码如下:

 1 bigNum sub(const bigNum &rhs)const
 2 {
 3     bigNum ans;
 4     memset(ans.a,0,sizeof(ans.a));
 5     int mlen=this->len;
 6     for(int i=0;i<mlen;++i){
 7         ans.a[i]+=this->a[i]-rhs.a[i];
 8         if(ans.a[i]<0){
 9             ans.a[i]+=10;
10             ans.a[i+1]-=1;//我们默认当前值大于后一个值,那么我们只需要无脑借位就好,借成-1也无所谓,最后效果是一样的
11         }
12     }
13     while(!ans.a[mlen]&&mlen>0) --mlen;//用于清除前导0
14     ans.len=mlen+1;
15     return ans;
16 }

对于大数乘法,就要稍微复杂一点了,不过原理依然是一样的,也是列竖式计算

观察图

 

 不难发现这一块便是一个大数加法,如果位数多了也是反复进行加法,控制好下标便很简单,建议拿纸对着代码模拟一遍

 1 bigNum mul(const bigNum &rhs)const
 2 {
 3     bigNum ans;
 4     memset(ans.a,0,sizeof(ans.a));
 5     int mlen=this->len+rhs.len;
 6     for(int i=0;i<this->len;++i){
 7         for(int j=0;j<rhs.len;++j){
 8             ans.a[j+i]+=this->a[i]*rhs.a[j];
 9             ans.a[j+i+1]+=ans.a[j+i]/10;
10             ans.a[j+i]%=10;
11         }
12     }
13     while(!ans.a[mlen]&&mlen>0) --mlen;//与前面一样,依然是去除前导零
14     ans.len=mlen+1;
15     return ans;
16 }

最后到了大数除法,由于高精除高精码量太多,而且很复杂,在此给出高精除低精的代码,看了代码在进行解释

(依然是列竖式进行计算)

 1 bigNum operator/(const int &rhs)const
 2 {
 3     bigNum ans;
 4     string s;
 5     int num=0;
 6     for(int i=len-1;i>=0;--i){
 7         s.push_back((num*10+a[i])/rhs+48);
 8         num=(num*10+a[i])%rhs;
 9     }
10     for(int i=0;s[0]==48;++i) s.erase(s.begin());//去除所有前导0
11     if(s.empty()) ans=0;//特判s是否为空,如果为空则输出个0(不然爆0)
12     else ans=s;
13     return ans;
14 }

6,7,8行为关键部分,我们从高位开始进行不断除-取余的运算,将余数取到次高位进行储存,这样不断往复,得到的便是除数,而最后剩下的num则为余数

最后奉上重载得差不多的大数类,可以进行大部分整数运算

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn=10005;
  7 class bigNum{
  8     friend istream &operator>>(istream &in,bigNum &n);
  9     friend ostream &operator<<(istream &out,const bigNum &n);//此处const很关键,决定了能否直接输出非左值 
 10     private:
 11         int a[maxn],len;
 12         char sign;
 13     public:
 14         bigNum():len(0){memset(a,0,sizeof(a));};
 15         bigNum(string s){change(s);};
 16         bigNum(int n){change(to_string(n));};
 17         void change(string s)
 18         {
 19             if(s[0]=='-'){
 20                 sign='-';
 21                 s.erase(s.begin());
 22             }
 23             else sign='+';
 24             len=s.size();
 25             for(int i=len-1;i>=0;--i) a[len-1-i]=s[i]-'0';
 26         }
 27         void print()const
 28         {
 29             if(sign=='-') cout<<this->sign;
 30             for(int i=len-1;i>=0;--i) cout<<this->a[i];
 31         }
 32         bigNum add(const bigNum &rhs)const
 33         {
 34             bigNum ans;//ÓÃÓÚ·µ»ØµÄans¶ÔÏó 
 35             memset(ans.a,0,sizeof(ans.a));
 36             int mlen=max(this->len,rhs.len),flag=0;
 37             for(int i=0;i<mlen;++i){
 38                 ans.a[i]=this->a[i]+rhs.a[i]+flag;
 39                 flag=0;
 40                 flag=ans.a[i]/10;
 41                 ans.a[i]%=10;
 42             }
 43             if(flag) ans.a[mlen++]=1;
 44             ans.len=mlen;
 45             return ans;
 46         }
 47         bigNum sub(const bigNum &rhs)const
 48         {
 49             bigNum ans;
 50             memset(ans.a,0,sizeof(ans.a));
 51             int mlen=this->len;
 52             for(int i=0;i<mlen;++i){
 53                 ans.a[i]+=this->a[i]-rhs.a[i];
 54                 if(ans.a[i]<0){
 55                     ans.a[i]+=10;
 56                     ans.a[i+1]-=1;
 57                 }
 58             }
 59             while(!ans.a[mlen]&&mlen>0) --mlen;
 60             ans.len=mlen+1;
 61             return ans;
 62         }
 63         bigNum mul(const bigNum &rhs)const
 64         {
 65             bigNum ans;
 66             memset(ans.a,0,sizeof(ans.a));
 67             int mlen=this->len+rhs.len;
 68             for(int i=0;i<this->len;++i){
 69                 for(int j=0;j<rhs.len;++j){
 70                     ans.a[j+i]+=this->a[i]*rhs.a[j];
 71                     ans.a[j+i+1]+=ans.a[j+i]/10;
 72                     ans.a[j+i]%=10;
 73                 }
 74             }
 75             while(!ans.a[mlen]&&mlen>0) --mlen;
 76             ans.len=mlen+1;
 77             return ans;
 78         }
 79     public:
 80         bigNum operator+(const bigNum &rhs)const
 81         {
 82             return this->add(rhs);
 83         }
 84         bigNum operator-(const bigNum &rhs)const
 85         {
 86             if(*this<rhs){
 87                 bigNum ans=rhs.sub(*this);
 88                 ans.sign='-';
 89                 return ans;
 90             }
 91             else return this->sub(rhs);
 92         }
 93         bigNum operator*(const bigNum &rhs)const
 94         {
 95             return this->mul(rhs);    
 96         }
 97         bigNum operator*(const int &rhs)const
 98         {
 99             return this->mul(to_string(rhs));
100         }
101         bigNum &operator+=(const bigNum &rhs)
102         {
103             *this=*this+rhs;
104             return *this;
105         }
106         bigNum &operator-=(const bigNum &rhs)
107         {
108             *this=*this-rhs;
109             return *this;
110         }
111         bigNum operator/(const int &rhs)const
112         {
113             bigNum ans;
114             string s;
115             int num=0;
116             for(int i=len-1;i>=0;--i){
117                 s.push_back((num*10+a[i])/rhs+48);
118                 num=(num*10+a[i])%rhs;
119             }
120             for(int i=0;s[0]==48;++i) s.erase(s.begin());
121             if(s.empty()) ans=0;
122             else ans=s;
123             return ans;
124         }
125         bigNum operator%(const int &rhs)const
126         {
127             bigNum ans;
128             string s;
129             int num=0;
130             for(int i=len-1;i>=0;--i){
131                 s.push_back((num*10+a[i])/rhs+48);
132                 num=(num*10+a[i])%rhs;
133             }
134             return num;
135         }
136         bool operator<(const bigNum &rhs)const
137         {
138             if(this->len<rhs.len) return 1;
139             else if(this->len>rhs.len) return 0;
140             else{
141                 int flag=0;
142                 for(int i=this->len-1;i>=0;--i){
143                     if(this->a[i]>rhs.a[i]){
144                         flag=0;
145                         break;
146                     }
147                     if(this->a[i]<rhs.a[i]){
148                         flag=1;
149                         break;
150                     }
151                 }
152                 return flag;
153             }
154         }
155         bool operator>(const bigNum &rhs)const
156         {
157             if(this->len>rhs.len) return 1;
158             else if(this->len<rhs.len) return 0;
159             else{
160                 int flag=0;
161                 for(int i=this->len-1;i>=0;--i){
162                     if(this->a[i]<rhs.a[i]){
163                         flag=0;
164                         break;
165                     }
166                     if(this->a[i]>rhs.a[i]){
167                         flag=1;
168                         break;
169                     }
170                 }
171                 return flag;
172             }
173         }
174         bool operator==(const bigNum &rhs) const
175         {
176             int flag=0;
177             if(this->len==rhs.len){
178                 flag=1;
179                 for(int i=0;i<this->len;++i){
180                     if(this->a[i]!=rhs.a[i]){
181                         flag=0;
182                         break;
183                     }
184                 }
185             }
186             return flag;
187         }
188 };
189 istream &operator>>(istream &in,bigNum &n)
190 {
191     string s;
192     in>>s;
193     n.change(s);
194     return in;
195 }
196 ostream &operator<<(ostream &out,const bigNum &n)
197 {
198     n.print();
199     return out;
200 }
201 int main()
202 {
203     int b;
204     bigNum a,c;
205     cin>>a>>c>>b;
206     cout<<a%b<<endl;
207     cout<<a*c<<endl;
208     cout<<a+c<<endl;
209     cout<<a-c<<endl;
210     cout<<a/b<<endl;
211     return 0;
212 }
View Code

 

posted @ 2019-04-09 22:08  Yilis  阅读(4376)  评论(0编辑  收藏  举报