[基础数据结构]高精度加减乘除
成员介绍:
1、value:记录每一位的数值
2、size:记录有几位
3、flag: true为正数 false为负数
其他:digits: 位数大小 为(long long) 1En = 10n
MaxS: 位数个数, 为 n
拆分:
一、初始化
void clear(){ memset(value,0,sizeof(value)); this->size = 1; this->flag = 0; return; }
二、数位更新
1、进位
void pushup(int i){ while(this->value[i] / digits > 0){ i++; this->value[i] += this->value[i-1] / digits; this->value[i-1] %= digits; } if(i > this->size && this->value[i]) this->size = i; //最后处理 更新size 并且保证有值 return; }
2、退位
void pushdown(){ while(!this->value[this->size])
this->size--; }
三、赋值
void operator = (long long x){ this->clear(); if(x == 0) return; if(x < 0) this->flag = 1,x = -x; this->value[1] = x; this->pushup(1); return; }
void operator = (BigInt x){ this->clear(); this->flag = x.flag; this->size = x.size; for(int i = 1;i <= x.size;i++) this->value[i] = x.value[i]; return; }
四、判断
1、==
bool operator == (BigInt x) const{ if(this->size != x.size) return false; if(this->flag != x.flag) return false; for(int i = 1;i <= x.size; i++) if(this->value[i] != x.value[i]) return false; return true; }
2、!=
bool operator != (BigInt x) const{ if(*this == x) return false; else return true; }
3、<
bool operator < (BigInt x) const{ if(*this == x) return false; if(this->flag && !x.flag) return true; if(!this->flag && x.flag) return false; //正负处理 bool flag = false; //以便于取负数 if(this->size < x.size) flag = true; else if(this->size > x.size) flag = false; else { for(int i = x.size;i >= 1;i--){ if(this->value[i] < x.value[i]){ //从大到小一旦有小于就处理 flag = true; break; } else if(this->value[i] > x.value[i]) break; //默认为false 直接break } } if(this->flag) flag = !flag; //负数处理 return flag; }
4、其他
bool operator > (BigInt x) const{ if(x < *this) return true; else return false; }
bool operator <= (BigInt x) const{ if(*this > x) return false; else return true; }
bool operator >= (BigInt x) const{ if(*this < x) return false; else return true; }
五、加法
BigInt operator + (BigInt x) const { if(!this->flag && x.flag) { x.flag = 0; return *this - x; } if(this->flag && !x.flag) { BigInt p = *this; p.flag = 0; return x - p; } //关于 正+负 = 正-正 的处理 x.size = max(this->size,x.size); int l = x.size; for(int i = 1;i <= l;i++){ x.value[i] += this->value[i]; x.pushup(i); //进位 } return x; }
六、减法(需要'<'号)
BigInt operator - (BigInt x) const { if(!this->flag && x.flag){ x.flag = 0; return *this + x; } if(this->flag && !x.flag){ x.flag = 1; return *this + x; } //正-负=正+正 负-正=负+负 BigInt p,q; if(*this == x) return p; //相等为0 else if(*this > x) x.flag = 0; // A-B=C 中 A>B则C>0;A<B则C<0 else x.flag = 1; p = *this, q = x; p.flag = 0; q.flag = 0; //取正处理 if(p < q) swap(p,q); x.size = max(p.size,q.size); //更新大小1 for(int i = 1;i <= x.size;i++){ if(p.value[i] < q.value[i]){ p.value[i] += digits; p.value[i + 1] -= 1; //借位 } x.value[i] = p.value[i] - q.value[i]; } x.pushdown(); //更新大小2 return x; }
七、乘法
BigInt operator * (BigInt x) const{ BigInt p; if(this->flag ^ x.flag) p.flag = 1; //同为正 异为负 for(int i = 1;i <= x.size;i++){ for(int j = 1;j <= this->size;j++){ p.value[i + j - 1] += x.value[i] * this->value[j]; //i+j-1要记住 p.pushup(i + j - 1); //进位 记住在 i+j-1开始进位 } } return p; }
八、除法
1、高精除以低精 (需'>')
基本思路:模拟手工除法,从高向低除求商,余数向低位进
注意:要对负数进行预处理
BigInt operator / (long long x) const{ BigInt p,q; bool flag1 = 0,flag2 = 0; if(x == 0) { //除数为0报错 cout<<"error"<<endl; p = INF; return p; } q = *this; if(x < 0){ //负数的预处理1 flag1 = 1; x = -x; } if(q.flag){ //负数的预处理2 flag2 = 1; q.flag = 0; } if(q < x) return p; //不预处理2,这里会出错 p = q; for(int i = p.size;i >=1; i--){ p.value[i - 1] += (p.value[i] % x) * digits; //余数向低位进 ;不预处理1,这里会出错 p.value[i] /= x; //求商;不预处理1,这里会出错 } p.flag = (flag1) ^ (flag2); //异或 p.pushdown(); return p; }
2、高精除以高精( 需要高精'+' '*' 高精除以低精'/'(或者另写高精除以2) )
基本思路:二分法
原理:商值 * 除数 <= 被除数 < 商值 * (除数+1) ,证明用脚指头都会
所以商值利用二分法找到,商值范围一定处在 0 ~ 被除数 之间
商值一定处于 digits被除数位数 - 除数位数-1 ~ digits被除数位数 - 除数位数 +1 之间
简单举例子,假设digits = 10 ; 8位除以5位
最小位:10000000 / 99999 = 100 为 102 , 2 = 8 - 5 -1;
最大位: 99999999 / 10000 = 9999 大约为 104 , 4 = 8 - 5 + 1;
但注意:
- 被除数位数 - 除数位数 - 1 可能会小于0
- 如果digits > 10时 digits被除数位数 - 除数位数+1 可能会大于 被除数
- 负数预处理
I、power 10处理:
static BigInt power_digits(int x){ BigInt p; p = 1; for(int i = 1;i <= x;i++) p *= digits; return p; } //写static才可以改变内部变量
II、整体代码:
BigInt operator / (BigInt x) const{ BigInt l,r,mid,p,q,ansl,ansr; bool flag1 = 0, flag2 = 0; if(x == 0) { cout<<"error"<<endl; //除数为0 报错 p = INF; return p; } q = *this; if(x.flag){ //负数预处理1 flag1 = 1; x.flag = 0; } if(q.flag){ //负数预处理2 flag2 = 1; q.flag = 0; } if(q < x) return p; //不负数预处理这里会出错 l = power_digits(max(0, q.size - x.size -1)), r = min(power_digits(q.size - x.size +1),q); //二分法初始化 while(l != r){ //二分法 mid = (l + r) / 2; ansl = mid * x; ansr = ansl + x; if(q >= ansl && q < ansr){ //符合 商值 * 除数 <= 被除数 < 商值 * (除数+1) p = mid; //若没有负数预处理这里都会出错 p.flag = (flag1) ^ (flag2); return p; } else if(q <= ansl) r = mid; else l = mid + 1; } return p; }
九、关于常数处理
TypeT operator ?? (long long x) const{ BigInt p; p = x; return *this ?? p; }
十、关于加减乘除赋值
void operator ??= (Type x) const{ *this = *this ?? x; return; }
十一、输出
int dig(int x){ //判断位数以便于输出前面的0 if(x == 0) return 1; int ans=0; while(x){ ans++; x /= 10; } return ans; } void print(){ if(this->flag) putchar('-'); cout<<this->value[size]; //先输出头,因为头前面不应该有0 for(int i = this->size - 1;i >= 1;i--){ for(int j = dig(this->value[i]);j < MaxS;j++) putchar('0'); //输出额外的0 cout<<value[i]; } return; }
十二、输入(需要'*'号)
void scan(){ this->clear(); char c = getchar(); bool flag = 0; //若用 this->flag 的话 若为负,则初始this为-0, 在 this = this *10 + (c^48)的时候会计算 -0 + (c^48) -> (c^48) - 0 导致this->flag = 0; while(c<'0' || c>'9') { if(c == '-') flag = 1; c = getchar(); } while(c>='0' && c <= '9'){ *this = *this * 10 + (c^48); c = getchar(); } if(flag) this->flag = 1; }
合体:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const long long digits = (long long) 1E8; 5 const int MaxS = 8; 6 const int INF = 0x3f3f3f3f; 7 8 9 struct BigInt{ 10 long long value[1234]; 11 int size; 12 bool flag; 13 14 void clear(){ 15 memset(value,0,sizeof(value)); 16 this->size = 1; 17 this->flag = 0; 18 return; 19 } 20 21 BigInt(){ 22 this->clear(); 23 } 24 25 void pushup(int i){ 26 while(this->value[i] / digits > 0){ 27 i++; 28 this->value[i] += this->value[i-1] / digits; 29 this->value[i-1] %= digits; 30 } 31 if(i > this->size && this->value[i]) this->size = i; //¸üÐÂsize ÇÒ±£Ö¤Õâ¸öµãÓÐÖµ 32 return; 33 } 34 35 void pushdown(){ 36 while(!this->value[this->size]) 37 this->size--; 38 } 39 40 void operator = (long long x){ 41 this->clear(); 42 if(x == 0) return; 43 if(x < 0) this->flag = 1,x = -x; 44 this->value[1] = x; 45 this->pushup(1); 46 return; 47 } 48 49 void operator = (BigInt x){ 50 this->clear(); 51 this->flag = x.flag; 52 this->size = x.size; 53 for(int i = 1;i <= x.size;i++) 54 this->value[i] = x.value[i]; 55 return; 56 } 57 58 bool operator == (BigInt x) const{ 59 if(this->size != x.size) return false; 60 if(this->flag != x.flag) return false; 61 for(int i = 1;i <= x.size; i++) 62 if(this->value[i] != x.value[i]) return false; 63 return true; 64 } 65 66 bool operator == (long long x) const{ 67 BigInt p; 68 p = x; 69 return *this == p; 70 } 71 72 bool operator != (BigInt x) const{ 73 if(*this == x) return false; 74 else return true; 75 } 76 77 bool operator != (long long x) const{ 78 if(*this == x) return false; 79 else return true; 80 } 81 82 bool operator < (BigInt x) const{ 83 if(*this == x) return false; 84 if(this->flag && !x.flag) return true; 85 if(!this->flag && x.flag) return false; 86 bool flag = false; 87 if(this->size < x.size) flag = true; 88 else if(this->size > x.size) flag = false; 89 else { 90 for(int i = x.size;i >= 1;i--){ 91 if(this->value[i] < x.value[i]){ 92 flag = true; 93 break; 94 } 95 else if(this->value[i] > x.value[i]) break; 96 } 97 } 98 if(this->flag) flag = !flag; 99 return flag; 100 } 101 102 bool operator < (long long x) const{ 103 BigInt p; 104 p = x; 105 return *this < p; 106 } 107 108 bool operator > (BigInt x) const{ 109 if(x < *this) return true; 110 else return false; 111 } 112 113 bool operator > (long long x) const{ 114 BigInt p; 115 p = x; 116 return *this > p; 117 } 118 119 bool operator <= (BigInt x) const{ 120 if(*this > x) return false; 121 else return true; 122 } 123 124 bool operator <= (long long x) const{ 125 if(*this > x) return false; 126 else return true; 127 } 128 129 bool operator >= (BigInt x) const{ 130 if(*this < x) return false; 131 else return true; 132 } 133 134 bool operator >= (long long x) const{ 135 if(*this < x) return false; 136 else return true; 137 } 138 139 BigInt operator + (BigInt x) const { 140 if(!this->flag && x.flag) { 141 x.flag = 0; 142 return *this - x; 143 } 144 if(this->flag && !x.flag) { 145 BigInt p = *this; 146 p.flag = 0; 147 return x - p; 148 } 149 x.size = max(this->size,x.size); 150 int l = x.size; 151 for(int i = 1;i <= l;i++){ 152 x.value[i] += this->value[i]; 153 x.pushup(i); 154 } 155 return x; 156 } 157 158 BigInt operator + (long long x) const{ 159 BigInt p; 160 p = x; 161 return *this + p; 162 } 163 164 void operator += (BigInt x) { 165 *this = *this + x; 166 return; 167 } 168 169 void operator += (long long x) { 170 *this = *this + x; 171 return; 172 } 173 174 BigInt operator - (BigInt x) const { 175 if(!this->flag && x.flag){ 176 x.flag = 0; 177 return *this + x; 178 } 179 if(this->flag && !x.flag){ 180 x.flag = 1; 181 return *this + x; 182 } 183 BigInt p,q; 184 if(*this == x) return p; 185 else if(*this > x) x.flag = 0; 186 else x.flag = 1; 187 p = *this, q = x; 188 p.flag = 0; q.flag = 0; 189 if(p < q) swap(p,q); 190 x.size = max(p.size,q.size); 191 for(int i = 1;i <= x.size;i++){ 192 if(p.value[i] < q.value[i]){ 193 p.value[i] += digits; 194 p.value[i + 1] -= 1; 195 } 196 x.value[i] = p.value[i] - q.value[i]; 197 } 198 x.pushdown(); 199 return x; 200 } 201 202 BigInt operator - (long long x) const{ 203 BigInt p; 204 p = x; 205 return *this - p; 206 } 207 208 void operator -= (BigInt x){ 209 *this = *this - x; 210 return; 211 } 212 213 void operator -= (long long x){ 214 *this = *this - x; 215 return; 216 } 217 218 BigInt operator * (BigInt x) const{ 219 BigInt p; 220 p.flag = this->flag ^ x.flag; 221 for(int i = 1;i <= x.size;i++){ 222 for(int j = 1;j <= this->size;j++){ 223 p.value[i + j - 1] += x.value[i] * this->value[j]; //i+j-1ÊÇÖØµã 224 p.pushup(i + j - 1); 225 } 226 } 227 return p; 228 } 229 230 BigInt operator * (long long x) const{ 231 BigInt p; 232 p = x; 233 return *this * p; 234 } 235 236 void operator *= (BigInt x){ 237 *this = *this * x; 238 return; 239 } 240 241 void operator *= (long long x){ 242 *this = *this * x; 243 return; 244 } 245 246 BigInt operator / (long long x) const{ 247 BigInt p,q; 248 bool flag1 = 0,flag2 = 0; 249 if(x == 0) { 250 cout<<"error"<<endl; 251 p = INF; 252 return p; 253 } 254 q = *this; 255 if(x < 0){ 256 flag1 = 1; 257 x = -x; 258 } 259 if(q.flag){ 260 flag2 = 1; 261 q.flag = 0; 262 } 263 if(q < x) return p; 264 p = q; 265 for(int i = p.size;i >=1; i--){ 266 p.value[i - 1] += (p.value[i] % x) * digits; 267 p.value[i] /= x; 268 } 269 p.flag = (flag1) ^ (flag2); 270 p.pushdown(); 271 return p; 272 } 273 274 BigInt operator / (BigInt x) const{ 275 BigInt l,r,mid,p,q,ansl,ansr; 276 bool flag1 = 0, flag2 = 0; 277 if(x == 0) { 278 cout<<"error"<<endl; 279 p = INF; 280 return p; 281 } 282 q = *this; 283 if(x.flag){ 284 flag1 = 1; 285 x.flag = 0; 286 } 287 if(q.flag){ 288 flag2 = 1; 289 q.flag = 0; 290 } 291 if(q < x) return p; 292 l = power_digits(max(0, q.size - x.size -1)), 293 r = min(power_digits(q.size - x.size +1),q); 294 while(l != r){ 295 mid = (l + r) / 2; 296 ansl = mid * x; 297 ansr = ansl + x; 298 if(q >= ansl && q < ansr){ 299 p = mid; 300 p.flag = (flag1) ^ (flag2); 301 return p; 302 } 303 else if(q <= ansl) r = mid; 304 else l = mid + 1; 305 } 306 return p; 307 } 308 309 static BigInt power_digits(int x){ 310 BigInt p; p = 1; 311 for(int i = 1;i <= x;i++) 312 p *= digits; 313 return p; 314 } 315 316 int dig(int x){ 317 if(x == 0) return 1; 318 int ans = 0; 319 while(x){ 320 ans++; 321 x /= 10; 322 } 323 return ans; 324 } 325 326 void print(){ 327 if(this->flag) putchar('-'); 328 cout<<this->value[size]; 329 for(int i = this->size - 1;i >= 1;i--){ 330 for(int j = dig(this->value[i]);j < MaxS;j++) 331 putchar('0'); 332 cout<<value[i]; 333 } 334 return; 335 } 336 337 void println(){ 338 this->print(); 339 putchar('\n'); 340 } 341 342 void scan(){ 343 this->clear(); 344 char c = getchar(); 345 bool flag = 0; 346 while(c<'0' || c>'9') { 347 if(c == '-') flag = 1; 348 c = getchar(); 349 } 350 while(c>='0' && c <= '9'){ 351 *this = *this * 10 + (c^48); 352 c = getchar(); 353 } 354 if(flag) this->flag = 1; 355 } 356 }que[51],de[51];