大数模板
1 #include<stdio.h> 2 #include<string.h> 3 #include<conio.h> 4 #include<stdlib.h> 5 #include<time.h> 6 #define N 1000 7 // 大数模板。。。 8 class BigNum 9 { 10 public: 11 int s[N]; //存放各位数字,s[0]为符号位,1代表正数,-1代表负数 12 //数组内高位存高位,123存在里面则为 1 3 2 1 ,第1个 1表示符号 13 int len; //长度 14 public: 15 BigNum() 16 { 17 memset(s,0,sizeof(s)); //初始化全0 18 s[0]=1; //默认正数 19 len=2; //变量初始化为0 20 } 21 int in() //输入 22 { 23 char tmp[N]; 24 int flag=scanf("%s",tmp); 25 *this=tmp; 26 return flag; 27 } 28 void out() //输出 29 { 30 if(s[0]==-1) printf("-"); 31 for(int i=len-1;i>0;i--) 32 printf("%d",s[i]); 33 } 34 void Clear() 35 { 36 memset(s,0,sizeof(s)); //初始化全0 37 s[0]=1; //默认正数 38 len=2; //变量初始化为0 39 } 40 BigNum Nizhi() //排除符号位颠倒数组 41 { 42 BigNum ans; 43 ans.s[0]=s[0]; 44 for(int i=1;i<=len/2;i++) 45 { 46 ans.s[i]=s[len-i]; 47 ans.s[len-i]=s[i]; 48 } 49 ans.len=len; 50 return ans; 51 } 52 friend bool operator<(const BigNum &a,const BigNum &b); 53 friend bool operator>(const BigNum &a,const BigNum &b); 54 friend bool operator<=(const BigNum &a,const BigNum &b); 55 friend bool operator>=(const BigNum &a,const BigNum &b); 56 friend BigNum operator+(BigNum a,BigNum b); 57 friend void operator+=(BigNum &a,BigNum b); 58 friend BigNum operator-(BigNum a,BigNum b); 59 friend void operator-=(BigNum &a,BigNum b); 60 friend BigNum operator*(BigNum a,BigNum b); 61 friend void operator*=(BigNum &a,BigNum b); 62 friend BigNum operator/(BigNum a,BigNum b); 63 friend void operator/=(BigNum &a,BigNum b); 64 friend BigNum operator%(BigNum &a,BigNum b); 65 friend void operator%=(BigNum &a,BigNum b); 66 friend bool operator==(const BigNum &a,const BigNum &b); 67 void operator=(const int a); 68 void operator=(const char *a); 69 BigNum operator--(); 70 BigNum operator--(int); 71 BigNum operator++(); 72 BigNum operator++(int); 73 }; 74 bool operator<(const BigNum &a,const BigNum &b) 75 { 76 bool flag; 77 if(a.s[0]==-1&&b.s[0]==1) return 1; //如果a为负,b为正,那么a<b 78 else if(a.s[0]==1&&b.s[0]==-1) return 0; //如果a为正,b为负,那么a>b 79 else if(a.s[0]==1&&b.s[0]==1) flag=1; //如果a、b都为正,flag=1,表示a、b大小和符号无关 80 else flag=0; //如果a、b都为负,flag=0,表示a、b大小和符号有关 81 // flag=1 时,a、b大小和除符号外的数字大小成正比,反之反比 82 if(a.len>b.len) return !flag; //a的位数多,所以a大,返回0 83 else if(a.len<b.len) return flag; //a的位数少,所以a小,返回1 84 else 85 { 86 int i=a.len; //从最高位开始比 87 while(i-->1) 88 { 89 if(a.s[i]>b.s[i]) return !flag; 90 else if(a.s[i]<b.s[i]) return flag; 91 } 92 return 0; //没有差异即相等返回0 93 } 94 } 95 bool operator<=(const BigNum &a,const BigNum &b) //同 < 96 { 97 bool flag; // flag=1 表示两者都是正的 =0表示两者都是负的 98 if(a.s[0]==-1&&b.s[0]==1) return 1; 99 else if(a.s[0]==1&&b.s[0]==-1) return 0; 100 else if(a.s[0]==1&&b.s[0]==1) flag=1; 101 else flag=0; 102 // flag 表示1 ,!flag 表示0 103 if(a.len>b.len) return !flag; 104 else if(a.len<b.len) return flag; 105 else 106 { 107 int i=a.len; 108 while(i-->1) 109 { 110 if(a.s[i]>b.s[i]) return !flag; 111 else if(a.s[i]<b.s[i]) return flag; 112 } 113 return 1; 114 } 115 } 116 bool operator>(const BigNum &a,const BigNum &b) 117 { 118 return !(a<=b); 119 } 120 bool operator>=(const BigNum &a,const BigNum &b) 121 { 122 return !(a<b); 123 } 124 bool operator==(const BigNum &a,const BigNum &b) 125 { 126 if(a.s[0]==-1&&b.s[0]==1) return 0; 127 else if(a.s[0]==1&&b.s[0]==-1) return 0; 128 if(a.len>b.len) return 0; 129 else if(a.len<b.len) return 0; 130 else 131 { 132 int i=a.len; 133 while(i-->1) 134 { 135 if(a.s[i]>b.s[i]) return 0; 136 else if(a.s[i]<b.s[i]) return 0; 137 } 138 return 1; 139 } 140 } 141 BigNum operator-(BigNum a,BigNum b) 142 { 143 BigNum ans; 144 if(a.s[0]==1&&b.s[0]==-1) //如果a正,b负,那么等同于a+|b| 145 { 146 b.s[0]=1; 147 return a+b; 148 } 149 else if(a.s[0]==-1&&b.s[0]==1) //如果a负,b正,那么等同于-(|a|+b) 150 { 151 a.s[0]=1; 152 ans=a+b; 153 ans.s[0]=-1; 154 return ans; 155 } 156 else if(a.s[0]==-1&&b.s[0]==-1) //如果a负,b负,那么等同于|b|-|a| 157 { 158 a.s[0]=1; 159 b.s[0]=1; 160 return b-a; 161 } 162 else //进到这一区域的,a为正,b为正 163 { 164 if(a<b) //如果a<b,那么等同于-(b-a) 165 { 166 ans=b-a; 167 ans.s[0]=-1; 168 } 169 else //进到这一区域a、b为正,且a>b,也就是说减出来的绝对是正数 170 { 171 int i=0; 172 int lm=a.len>b.len?a.len:b.len; //由于减出来必定是正数,不需要考虑lm-1位<0的情况 173 for(int i=1;i<lm;i++) 174 { 175 int tmp=ans.s[i]+a.s[i]-b.s[i]; 176 if(tmp<0) 177 { 178 ans.s[i+1]--; 179 tmp+=10; 180 } 181 ans.s[i]=tmp; 182 } 183 while(lm>2) //清楚高位0,最多清楚到0为止 184 { 185 if(ans.s[lm-1]==0) lm--; 186 else break; 187 } 188 ans.len=lm; 189 } 190 } 191 return ans; 192 } 193 void operator-=(BigNum &a,BigNum b) 194 { 195 a=a-b; 196 } 197 BigNum operator+(BigNum a,BigNum b) 198 { 199 BigNum ans; 200 int lm=a.len>b.len?a.len:b.len; 201 if(a.s[0]*b.s[0]==1) //如果两者符号位相同 202 { 203 ans.s[0]=a.s[0]; //结果符号位与任意一个相同 204 for(int i=1;i<lm;i++) 205 { 206 int tmp=ans.s[i]+a.s[i]+b.s[i]; 207 if(tmp>=10) 208 { 209 ans.s[i+1]++; 210 } 211 ans.s[i]=tmp%10; 212 } 213 if(ans.s[lm]==0) ans.len=lm; //如果最高位没有进位,那么长度不变,否则加1 214 else ans.len=lm+1; 215 } 216 else //如果a、b符号不同,可以转化为减法 217 { 218 if(a.s[0]==1) 219 { 220 b.s[0]=1; 221 return a-b; 222 } 223 else 224 { 225 a.s[0]=1; 226 return b-a; 227 } 228 } 229 return ans; 230 } 231 void operator+=(BigNum &a,BigNum b) 232 { 233 a=a+b; 234 } 235 236 BigNum operator*(BigNum a,BigNum b) 237 { 238 BigNum ans; 239 ans.s[0]=a.s[0]*b.s[0]; //乘法和除法的符号位简单处理 240 for(int i=1;i<a.len;i++) 241 { 242 for(int j=1;j<b.len;j++) 243 { 244 ans.s[i+j-1]+=a.s[i]*b.s[j]; //先存 245 } 246 } 247 int maxt=a.len+b.len; //最多位数 248 for(int i=1;i<maxt;i++) //处理每个位上的数 249 { 250 if(ans.s[i]>=10) 251 { 252 ans.s[i+1]+=ans.s[i]/10; 253 ans.s[i]=ans.s[i]%10; 254 } 255 } 256 int i; 257 for(i=maxt;i>1;i--) //处理高位0 258 { 259 if(ans.s[i]!=0) break; 260 } 261 ans.len=i+1; 262 return ans; 263 } 264 void operator*=(BigNum &a,BigNum b) 265 { 266 a=a*b; 267 } 268 BigNum operator/(BigNum a,BigNum b) 269 { 270 /* 271 思路: 首先从a的高位往低位数,如果还<b,那么就再加1位,知道>=b,然后遍历1-9,判断此时 272 合适取值,和平常手动计算思路一样 273 */ 274 BigNum ans; 275 ans.s[0]=a.s[0]*b.s[0]; 276 b.s[0]=1; //中途比较需要 277 BigNum tmp; //添位取值 278 tmp.len=1; //刚开始为无值,就是说连a的最高位都还没纳入 279 BigNum zj; //中间变量,比较时需要,由于数组是倒置的,所以加这一变量 280 ans.len=1; //答案还是空的 281 int j=a.len; //j固定指向a,不断取值 282 bool match=1; //match为0退出循环 283 while(1) 284 { 285 while(1) //如果还没取够值,就继续加位 286 { 287 if(j==1) //如果a到了符号位,那么可以退出循环了 288 { 289 match=0; 290 break; 291 } 292 tmp.s[tmp.len++]=a.s[--j]; //加位,由于开始不好确定位数,所以直接正向不好办 293 zj=tmp.Nizhi(); //数组颠倒后再去比较 294 if(b<=zj) break; //如果b<=zj了,就可以退出了,否则该位为0 295 ans.s[ans.len++]=0; 296 } 297 if(!match) break; //match为0退出循环 298 int i; 299 BigNum r=b; //r为最大容许的乘后值 300 for(i=2;i<=10;i++) 301 { 302 BigNum p; 303 p.s[p.len-1]=i; //获得 2 - 10 . 赋值过程不符常规,但由于下一步是乘,可以忽略该bug 304 BigNum u=b*p; //如果u超过了中间变量,可以退出了,同i应该减1 305 if(zj<u) break; 306 r=u; //乘得的最大数 307 } 308 i--; 309 ans.s[ans.len++]=i; //逐位求值 310 zj=zj-r; //获得余数 311 BigNum q; 312 if(zj==q) zj.len--; //如果余数为0,那么去掉,不能出现00,不然会出错 313 tmp=zj.Nizhi(); //重新逆置 314 } 315 ans=ans.Nizhi(); //逆置获得答案 316 while(ans.s[ans.len-1]==0&&ans.len>2) //高位消0 317 { 318 ans.len--; 319 } 320 return ans; 321 } 322 void operator/=(BigNum &a,BigNum b) 323 { 324 a=a/b; 325 } 326 BigNum operator%(BigNum &a,BigNum b) 327 { 328 b.s[0]=1; 329 BigNum tmp; 330 tmp.len=1; 331 BigNum zj; 332 int j=a.len; 333 bool match=1; 334 while(1) 335 { 336 while(1) 337 { 338 if(j==1) 339 { 340 match=0; 341 break; 342 } 343 tmp.s[tmp.len++]=a.s[--j]; 344 zj=tmp.Nizhi(); 345 if(b<=zj) break; 346 } 347 if(!match) break; 348 int i; 349 BigNum r=b; 350 for(i=2;i<=10;i++) 351 { 352 BigNum p; 353 p.s[p.len-1]=i; 354 BigNum u=b*p; 355 if(zj<u) break; 356 r=u; 357 } 358 i--; 359 zj=zj-r; 360 BigNum q; 361 if(zj==q) zj.len--; 362 tmp=zj.Nizhi(); 363 } 364 if(zj.len==1) 365 { 366 zj.Clear(); 367 } 368 return zj; 369 } 370 void operator%=(BigNum &a,BigNum b) 371 { 372 a=a%b; 373 } 374 void BigNum::operator=(int a) 375 { 376 Clear(); 377 if(a<0) 378 { 379 s[0]=-1; 380 a=-a; 381 } 382 len=1; 383 while(a) 384 { 385 s[len++]=a%10; 386 a/=10; 387 } 388 } 389 void BigNum::operator=(const char *a) 390 { 391 Clear(); 392 if(*a=='-') 393 { 394 s[0]=-1; 395 a++; 396 } 397 len=1; 398 while(*a&&*a=='0') a++; 399 while(*a) 400 { 401 s[len++]=*a-'0'; 402 a++; 403 } 404 if(len==1) len=2; 405 *this=Nizhi(); 406 } 407 BigNum BigNum::operator--() // --a; 408 { 409 BigNum tmp; 410 tmp=-1; 411 *this+=tmp; 412 return *this; 413 } 414 BigNum BigNum::operator--(int) // a--; 415 { 416 BigNum ans; 417 ans=*this; 418 BigNum tmp; 419 tmp=-1; 420 *this+=tmp; 421 return ans; 422 } 423 BigNum BigNum::operator++() // ++a; 424 { 425 BigNum tmp; 426 tmp=1; 427 *this+=tmp; 428 return *this; 429 } 430 BigNum BigNum::operator++(int) // a++; 431 { 432 BigNum ans; 433 ans=*this; 434 BigNum tmp; 435 tmp=1; 436 *this+=tmp; 437 return ans; 438 } 439 int main() 440 { 441 442 return 0; 443 }