00001 #include <iostream.h>
00002 #include <stdlib.h>
00003 #include <ctype.h>
00004 #include <limits.h>
00005 #include "bigint.h"
00006 #include "apvector.h"
00007
00008 const int BASE = 10;
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 BigInt::BigInt()
00040
00041 : mySign(positive),
00042 myDigits(1,'0'),
00043 myNumDigits(1)
00044 {
00045
00046 }
00047
00048 BigInt::BigInt(int num)
00049
00050 : mySign(positive),
00051 myDigits(1,'0'),
00052 myNumDigits(0)
00053 {
00054
00055
00056 if (num < 0)
00057 {
00058 mySign = negative;
00059 num = -1 * num;
00060 }
00061
00062
00063
00064 AddSigDigit(num % BASE);
00065 num = num / BASE;
00066
00067
00068
00069 while (num != 0)
00070 {
00071 AddSigDigit(num % BASE);
00072 num = num / BASE;
00073 }
00074 }
00075
00076
00077 BigInt::BigInt(const apstring & s)
00078
00079
00080
00081
00082 : mySign(positive),
00083 myDigits(s.length(),'0'),
00084 myNumDigits(0)
00085 {
00086 int k;
00087 int limit = 0;
00088
00089 if (s.length() == 0)
00090 {
00091 myDigits.resize(1);
00092 AddSigDigit(0);
00093 return;
00094 }
00095 if (s[0] == '-')
00096 {
00097 mySign = negative;
00098 limit = 1;
00099 }
00100 if (s[0] == '+')
00101 {
00102 limit = 1;
00103 }
00104
00105
00106 for(k=s.length() - 1; k >= limit; k--)
00107 {
00108 if (! isdigit(s[k]))
00109 {
00110 cerr << "badly formed BigInt value = " << s << endl;
00111 abort();
00112 }
00113 AddSigDigit(s[k]-'0');
00114 }
00115 Normalize();
00116 }
00117
00118
00119 const BigInt & BigInt::operator +=(const BigInt & rhs)
00120
00121 {
00122
00123 int sum;
00124 int carry = 0;
00125
00126 int k;
00127 int len = NumDigits();
00128
00129 if (rhs == 0){
00130 return *this;
00131 }
00132
00133 if (IsPositive() != rhs.IsPositive())
00134 {
00135 *this -= (-1 * rhs);
00136 return *this;
00137 }
00138
00139
00140
00141 if (len < rhs.NumDigits())
00142 {
00143 len = rhs.NumDigits();
00144 }
00145 for(k=0; k < len; k++)
00146 {
00147 sum = GetDigit(k) + rhs.GetDigit(k) + carry;
00148 carry = sum / BASE;
00149 sum = sum % BASE;
00150
00151 if (k < myNumDigits)
00152 {
00153 ChangeDigit(k,sum);
00154 }
00155 else
00156 {
00157 AddSigDigit(sum);
00158 }
00159 }
00160 if (carry != 0)
00161 {
00162 AddSigDigit(carry);
00163 }
00164 return *this;
00165 }
00166
00167
00168 const BigInt & BigInt::operator -=(const BigInt & rhs)
00169
00170 {
00171 int diff;
00172 int borrow = 0;
00173
00174 int k;
00175 int len = NumDigits();
00176
00177 if (rhs == 0){
00178 return *this;
00179 }
00180
00181
00182
00183 if (IsNegative() != rhs.IsNegative())
00184 {
00185 *this +=(-1 * rhs);
00186 return *this;
00187 }
00188
00189
00190
00191
00192
00193 if (IsPositive() && (*this) < rhs ||
00194 IsNegative() && (*this) > rhs)
00195 {
00196 *this = rhs - *this;
00197 if (IsPositive()) mySign = negative;
00198 else mySign = positive;
00199 return *this;
00200 }
00201
00202
00203 for(k=0; k < len; k++)
00204 {
00205 diff = GetDigit(k) - rhs.GetDigit(k) - borrow;
00206 borrow = 0;
00207 if (diff < 0)
00208 {
00209 diff += 10;
00210 borrow = 1;
00211 }
00212 ChangeDigit(k,diff);
00213 }
00214 Normalize();
00215 return *this;
00216 }
00217
00218 BigInt operator +(const BigInt & lhs, const BigInt & rhs)
00219
00220 {
00221 BigInt result(lhs);
00222 result += rhs;
00223 return result;
00224 }
00225
00226 BigInt operator -(const BigInt & lhs, const BigInt & rhs)
00227
00228 {
00229 BigInt result(lhs);
00230 result -= rhs;
00231 return result;
00232 }
00233
00234 void BigInt::Print(ostream & os) const
00235
00236 {
00237 os << ToString();
00238 }
00239
00240 apstring BigInt::ToString() const
00241
00242 {
00243 int k;
00244 int len = NumDigits();
00245 apstring s = "";
00246
00247 if (IsNegative())
00248 {
00249 s = '-';
00250 }
00251 for(k=len-1; k >= 0; k--)
00252 {
00253 s += char('0'+GetDigit(k));
00254 }
00255 return s;
00256 }
00257
00258 int BigInt::ToInt() const
00259
00260
00261 {
00262 int result = 0;
00263 int k;
00264 if (INT_MAX < *this) return INT_MAX;
00265 if (*this < INT_MIN) return INT_MIN;
00266
00267 for(k=NumDigits()-1; k >= 0; k--)
00268 {
00269 result = result * 10 + GetDigit(k);
00270 }
00271 if (IsNegative())
00272 {
00273 result *= -1;
00274 }
00275 return result;
00276 }
00277
00278 double BigInt::ToDouble() const
00279
00280
00281 {
00282 double result = 0.0;
00283 int k;
00284 for(k=NumDigits()-1; k >= 0; k--)
00285 {
00286 result = result * 10 + GetDigit(k);
00287 }
00288 if (IsNegative())
00289 {
00290 result *= -1;
00291 }
00292 return result;
00293 }
00294
00295 ostream & operator <<(ostream & out, const BigInt & big)
00296
00297 {
00298 big.Print(out);
00299 return out;
00300 }
00301
00302 istream & operator >> (istream & in, BigInt & big)
00303
00304 {
00305 apstring s;
00306 in >> s;
00307 big = BigInt(s);
00308 return in;
00309 }
00310
00311 bool operator == (const BigInt & lhs, const BigInt & rhs)
00312
00313 {
00314 return lhs.Equal(rhs);
00315 }
00316
00317 bool BigInt::Equal(const BigInt & rhs) const
00318
00319 {
00320
00321 if (NumDigits() != rhs.NumDigits() || IsNegative() != rhs.IsNegative())
00322 {
00323 return false;
00324 }
00325
00326
00327 int k;
00328 int len = NumDigits();
00329 for(k=0; k < len; k++)
00330 {
00331 if (GetDigit(k) != rhs.GetDigit(k)) return false;
00332 }
00333
00334 return true;
00335 }
00336
00337 bool operator != (const BigInt & lhs, const BigInt & rhs)
00338
00339 {
00340 return ! (lhs == rhs);
00341 }
00342
00343 bool operator < (const BigInt & lhs, const BigInt & rhs)
00344
00345 {
00346 return lhs.LessThan(rhs);
00347 }
00348
00349 bool BigInt::LessThan(const BigInt & rhs) const
00350
00351 {
00352
00353
00354 if (IsNegative() != rhs.IsNegative())
00355 {
00356 return IsNegative();
00357 }
00358
00359
00360
00361 if (NumDigits() != rhs.NumDigits())
00362 {
00363 return (NumDigits() < rhs.NumDigits() && IsPositive()) ||
00364 (NumDigits() > rhs.NumDigits() && IsNegative());
00365 }
00366
00367
00368
00369 int k;
00370 int len = NumDigits();
00371
00372 for(k=len-1; k >= 0; k--)
00373 {
00374 if (GetDigit(k) < rhs.GetDigit(k)) return IsPositive();
00375 if (GetDigit(k) > rhs.GetDigit(k)) return IsNegative();
00376 }
00377 return false;
00378 }
00379
00380 bool operator > (const BigInt & lhs, const BigInt & rhs)
00381
00382 {
00383 return rhs < lhs;
00384 }
00385
00386 bool operator <= (const BigInt & lhs, const BigInt & rhs)
00387
00388 {
00389 return lhs == rhs || lhs < rhs;
00390 }
00391 bool operator >= (const BigInt & lhs, const BigInt & rhs)
00392
00393 {
00394 return lhs == rhs || lhs > rhs;
00395 }
00396
00397 void BigInt::Normalize()
00398
00399 {
00400 int k;
00401 int len = NumDigits();
00402 for(k=len-1; k >= 0; k--)
00403 {
00404 if (GetDigit(k) != 0) break;
00405 myNumDigits--;
00406 }
00407 if (k < 0)
00408 {
00409 myNumDigits = 1;
00410 mySign = positive;
00411 }
00412 }
00413
00414
00415 const BigInt & BigInt::operator *=(int num)
00416
00417 {
00418 int carry = 0;
00419 int product;
00420 int k;
00421 int len = NumDigits();
00422
00423 if (0 == num)
00424 {
00425 *this = 0;
00426 return *this;
00427 }
00428
00429 if (BASE < num|| num < 0)
00430 {
00431 *this *= BigInt(num);
00432 return *this;
00433 }
00434
00435 if (1 == num)
00436 {
00437 return *this;
00438 }
00439
00440 for(k=0; k < len; k++)
00441 {
00442 product = num * GetDigit(k) + carry;
00443 carry = product/BASE;
00444 ChangeDigit(k,product % BASE);
00445 }
00446
00447 while (carry != 0)
00448 {
00449 AddSigDigit(carry % BASE);
00450 carry /= BASE;
00451 }
00452 return *this;
00453 }
00454
00455
00456 BigInt operator *(const BigInt & a, int num)
00457
00458 {
00459 BigInt result(a);
00460 result *= num;
00461 return result;
00462 }
00463
00464 BigInt operator *(int num, const BigInt & a)
00465
00466 {
00467 BigInt result(a);
00468 result *= num;
00469 return result;
00470 }
00471
00472
00473 const BigInt & BigInt::operator *=(const BigInt & rhs)
00474
00475 {
00476
00477
00478 if (IsNegative() != rhs.IsNegative())
00479 {
00480 mySign = negative;
00481 }
00482 else
00483 {
00484 mySign = positive;
00485 }
00486
00487 BigInt sum(0);
00488 int k;
00489 int len = rhs.NumDigits();
00490
00491 for(k=0; k < len; k++)
00492 {
00493 sum += (*this) * rhs.GetDigit(k);
00494 (*this) *= 10;
00495 }
00496 *this = sum;
00497 return *this;
00498 }
00499
00500 BigInt operator *(const BigInt & lhs, const BigInt & rhs)
00501
00502 {
00503 BigInt result(lhs);
00504 result *= rhs;
00505 return result;
00506 }
00507
00508 int BigInt::NumDigits() const
00509
00510 {
00511 return myNumDigits;
00512 }
00513
00514 int BigInt::GetDigit(int k) const
00515
00516
00517
00518
00519 {
00520 if (0 <= k && k < NumDigits())
00521 {
00522 return myDigits[k] - '0';
00523 }
00524 return 0;
00525 }
00526
00527 void BigInt::ChangeDigit(int k, int value)
00528
00529
00530
00531 {
00532 if (0 <= k && k < NumDigits())
00533 {
00534 myDigits[k] = char('0' + value);
00535 }
00536 else
00537 {
00538 cerr << "error changeDigit " << k << " " << myNumDigits << endl;
00539 }
00540 }
00541
00542 void BigInt::AddSigDigit(int value)
00543
00544
00545 {
00546 if (myNumDigits >= myDigits.length())
00547 {
00548 myDigits.resize(myDigits.length() * 2);
00549 }
00550 myDigits[myNumDigits] = char('0' + value);
00551 myNumDigits++;
00552 }
00553
00554 bool BigInt::IsNegative() const
00555
00556 {
00557 return mySign == negative;
00558 }
00559
00560 bool BigInt::IsPositive() const
00561
00562 {
00563 return mySign == positive;
00564 }