00001 #include <iostream.h>
00002 #include <stdlib.h>
00003 #include <ctype.h>
00004 #include <limits.h>
00005 #include "bigint1.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
00040 BigInt::BigInt()
00041
00042 : mySign(positive),
00043 myDigits(1,'0'),
00044 myNumDigits(1)
00045 {
00046
00047 }
00048
00049 BigInt::BigInt(int num)
00050
00051 : mySign(positive),
00052 myDigits(1,'0'),
00053 myNumDigits(0)
00054 {
00055
00056
00057 if (num < 0)
00058 {
00059 mySign = negative;
00060 num = -1 * num;
00061 }
00062
00063
00064
00065 AddSigDigit(num % BASE);
00066 num = num / BASE;
00067
00068
00069
00070 while (num != 0)
00071 {
00072 AddSigDigit(num % BASE);
00073 num = num / BASE;
00074 }
00075 }
00076
00077
00078 BigInt::BigInt(const apstring & s)
00079
00080
00081
00082
00083 : mySign(positive),
00084 myDigits(s.length(),'0'),
00085 myNumDigits(0)
00086 {
00087 int k;
00088 int limit = 0;
00089
00090 if (s.length() == 0)
00091 {
00092 myDigits.resize(1);
00093 AddSigDigit(0);
00094 return;
00095 }
00096 if (s[0] == '-')
00097 {
00098 mySign = negative;
00099 limit = 1;
00100 }
00101 if (s[0] == '+')
00102 {
00103 limit = 1;
00104 }
00105
00106
00107 for(k=s.length() - 1; k >= limit; k--)
00108 {
00109 if (! isdigit(s[k]))
00110 {
00111 cerr << "badly formed BigInt value = " << s << endl;
00112 abort();
00113 }
00114 AddSigDigit(s[k]-'0');
00115 }
00116 Normalize();
00117 }
00118
00119
00120 const BigInt & BigInt::operator +=(const BigInt & rhs)
00121
00122 {
00123
00124 int sum;
00125 int carry = 0;
00126
00127 int k;
00128 int len = NumDigits();
00129
00130 if (this == &rhs)
00131 {
00132 *this *= 2;
00133 return *this;
00134 }
00135
00136 if (rhs == 0){
00137 return *this;
00138 }
00139
00140 if (IsPositive() != rhs.IsPositive())
00141 {
00142 *this -= (-1 * rhs);
00143 return *this;
00144 }
00145
00146
00147
00148 if (len < rhs.NumDigits())
00149 {
00150 len = rhs.NumDigits();
00151 }
00152 for(k=0; k < len; k++)
00153 {
00154 sum = GetDigit(k) + rhs.GetDigit(k) + carry;
00155 carry = sum / BASE;
00156 sum = sum % BASE;
00157
00158 if (k < myNumDigits)
00159 {
00160 ChangeDigit(k,sum);
00161 }
00162 else
00163 {
00164 AddSigDigit(sum);
00165 }
00166 }
00167 if (carry != 0)
00168 {
00169 AddSigDigit(carry);
00170 }
00171 return *this;
00172 }
00173
00174 BigInt operator +(const BigInt & lhs, const BigInt & rhs)
00175
00176 {
00177 BigInt result(lhs);
00178 result += rhs;
00179 return result;
00180 }
00181
00182
00183
00184
00185
00186
00187 const BigInt & BigInt::operator -=(const BigInt & rhs)
00188
00189 {
00190 }
00191
00192 const BigInt & BigInt::operator *=(int num)
00193
00194 {
00195 }
00196
00197 BigInt operator *(int num, const BigInt & a)
00198
00199 {
00200 }
00201
00202
00203
00204 void BigInt::Print(ostream & os) const
00205
00206 {
00207 os << ToString();
00208 }
00209
00210 apstring BigInt::ToString() const
00211
00212 {
00213 int k;
00214 int len = NumDigits();
00215 apstring s = "";
00216
00217 if (IsNegative())
00218 {
00219 s = '-';
00220 }
00221 for(k=len-1; k >= 0; k--)
00222 {
00223 s += char('0'+GetDigit(k));
00224 }
00225 return s;
00226 }
00227
00228 int BigInt::ToInt() const
00229
00230
00231 {
00232 int result = 0;
00233 int k;
00234 if (INT_MAX < *this) return INT_MAX;
00235 if (*this < INT_MIN) return INT_MIN;
00236
00237 for(k=NumDigits()-1; k >= 0; k--)
00238 {
00239 result = result * 10 + GetDigit(k);
00240 }
00241 if (IsNegative())
00242 {
00243 result *= -1;
00244 }
00245 return result;
00246 }
00247
00248 double BigInt::ToDouble() const
00249
00250
00251 {
00252 double result = 0.0;
00253 int k;
00254 for(k=NumDigits()-1; k >= 0; k--)
00255 {
00256 result = result * 10 + GetDigit(k);
00257 }
00258 if (IsNegative())
00259 {
00260 result *= -1;
00261 }
00262 return result;
00263 }
00264
00265 ostream & operator <<(ostream & out, const BigInt & big)
00266
00267 {
00268 big.Print(out);
00269 return out;
00270 }
00271
00272 istream & operator >> (istream & in, BigInt & big)
00273
00274 {
00275 apstring s;
00276 in >> s;
00277 big = BigInt(s);
00278 return in;
00279 }
00280
00281 bool operator == (const BigInt & lhs, const BigInt & rhs)
00282
00283 {
00284 return lhs.Equal(rhs);
00285 }
00286
00287 bool BigInt::Equal(const BigInt & rhs) const
00288
00289 {
00290
00291 if (NumDigits() != rhs.NumDigits() || IsNegative() != rhs.IsNegative())
00292 {
00293 return false;
00294 }
00295
00296
00297 int k;
00298 int len = NumDigits();
00299 for(k=0; k < len; k++)
00300 {
00301 if (GetDigit(k) != rhs.GetDigit(k)) return false;
00302 }
00303
00304 return true;
00305 }
00306
00307 bool operator != (const BigInt & lhs, const BigInt & rhs)
00308
00309 {
00310 return ! (lhs == rhs);
00311 }
00312
00313 bool operator < (const BigInt & lhs, const BigInt & rhs)
00314
00315 {
00316 return lhs.LessThan(rhs);
00317 }
00318
00319 bool BigInt::LessThan(const BigInt & rhs) const
00320
00321 {
00322
00323
00324 if (IsNegative() != rhs.IsNegative())
00325 {
00326 return IsNegative();
00327 }
00328
00329
00330
00331 if (NumDigits() != rhs.NumDigits())
00332 {
00333 return (NumDigits() < rhs.NumDigits() && IsPositive()) ||
00334 (NumDigits() > rhs.NumDigits() && IsNegative());
00335 }
00336
00337
00338
00339 int k;
00340 int len = NumDigits();
00341
00342 for(k=len-1; k >= 0; k--)
00343 {
00344 if (GetDigit(k) < rhs.GetDigit(k)) return IsPositive();
00345 if (GetDigit(k) > rhs.GetDigit(k)) return IsNegative();
00346 }
00347 return false;
00348 }
00349
00350 bool operator > (const BigInt & lhs, const BigInt & rhs)
00351
00352 {
00353 return rhs < lhs;
00354 }
00355
00356 bool operator <= (const BigInt & lhs, const BigInt & rhs)
00357
00358 {
00359 return lhs == rhs || lhs < rhs;
00360 }
00361 bool operator >= (const BigInt & lhs, const BigInt & rhs)
00362
00363 {
00364 return lhs == rhs || lhs > rhs;
00365 }
00366
00367 void BigInt::Normalize()
00368
00369 {
00370 int k;
00371 int len = NumDigits();
00372 for(k=len-1; k >= 0; k--)
00373 {
00374 if (GetDigit(k) != 0) break;
00375 myNumDigits--;
00376 }
00377 if (k < 0)
00378 {
00379 myNumDigits = 1;
00380 mySign = positive;
00381 }
00382 }
00383
00384
00385
00386 int BigInt::NumDigits() const
00387
00388 {
00389 return myNumDigits;
00390 }
00391
00392 int BigInt::GetDigit(int k) const
00393
00394
00395
00396
00397 {
00398 if (0 <= k && k < NumDigits())
00399 {
00400 return myDigits[k] - '0';
00401 }
00402 return 0;
00403 }
00404
00405 void BigInt::ChangeDigit(int k, int value)
00406
00407
00408
00409 {
00410 if (0 <= k && k < NumDigits())
00411 {
00412 myDigits[k] = char('0' + value);
00413 }
00414 else
00415 {
00416 cerr << "error changeDigit " << k << " " << myNumDigits << endl;
00417 }
00418 }
00419
00420 void BigInt::AddSigDigit(int value)
00421
00422
00423 {
00424 if (myNumDigits >= myDigits.length())
00425 {
00426 myDigits.resize(myDigits.length() * 2);
00427 }
00428 myDigits[myNumDigits] = char('0' + value);
00429 myNumDigits++;
00430 }
00431
00432 bool BigInt::IsNegative() const
00433
00434 {
00435 return mySign == negative;
00436 }
00437
00438 bool BigInt::IsPositive() const
00439
00440 {
00441 return mySign == positive;
00442 }