Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

bigint1.C

Go to the documentation of this file.
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 // author: Owen Astrachan
00011 //
00012 //****************************************************************
00013 //  bigint1.cpp
00014 //
00015 //  Modified January 8, 1998,  Chris Nevison
00016 //
00017 //  Modification removes operators -= *= (int) * (int, BigInt)
00018 //  for use with lab for creating stubs.
00019 //****************************************************************
00020 //
00021 // BigInts are implemented using a Vector<char> to store
00022 // the digits of a BigInt
00023 // Currently a number like 5,879 is stored as the vector {9,7,8,5}
00024 // i.e., the least significant digit is the first digit in the vector;
00025 // for example, GetDigit(0) returns 9 and getDigit(3) returns 5.
00026 // All operations on digits should be done using private
00027 // helper functions:
00028 //
00029 // int  GetDigit(k)        -- return k-th digit
00030 // void ChangeDigit(k,val) -- set k-th digit to val
00031 // void AddSigDigit(val)   -- add new most significant digit val
00032 //
00033 // by performing all ops in terms of these private functions we
00034 // make implementation changes simpler
00035 // 
00036 // I/O operations are facilitated by the ToString() member function
00037 // which converts a BigInt to its string (ASCII) representation
00038 
00039 
00040 BigInt::BigInt()
00041 // postcondition: bigint initialized to 0
00042    : mySign(positive),
00043      myDigits(1,'0'),
00044      myNumDigits(1)
00045 {
00046         // all fields initialized in initializer list
00047 }
00048 
00049 BigInt::BigInt(int num)
00050 // postcondition: bigint initialized to num
00051    : mySign(positive),
00052      myDigits(1,'0'),
00053      myNumDigits(0)
00054 { 
00055     // check if num is negative, change state and num accordingly
00056     
00057     if (num < 0)
00058     {
00059         mySign = negative;
00060         num = -1 * num;
00061     }
00062 
00063     // handle least-significant digit of num (handles num == 0)
00064     
00065     AddSigDigit(num % BASE);
00066     num = num / BASE;
00067     
00068     // handle remaining digits of num
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 // precondition: s consists of digits only, optionally preceded by + or - 
00080 // postcondition: bigint initialized to integer represented by s
00081 //                if s is not a well-formed BigInt (e.g., contains non-digit
00082 //                characters) then an error message is printed and abort called
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     // start at least significant digit
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 // postcondition: returns value of bigint + rhs after addition
00122 {
00123 
00124     int sum;
00125     int carry = 0;
00126 
00127     int k;
00128     int len = NumDigits();         // length of larger addend
00129 
00130     if (this == &rhs)              // to add self, multiply by 2
00131     {
00132         *this *= 2;
00133         return *this;
00134     }
00135 
00136     if (rhs == 0){
00137       return *this;
00138     }
00139 
00140     if (IsPositive() != rhs.IsPositive())    // signs not the same, subtract
00141     {
00142         *this -= (-1 * rhs);
00143         return *this;
00144     }
00145 
00146     // process both numbers until one is exhausted
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 // postcondition: returns a bigint whose value is lhs + rhs
00176 {
00177     BigInt result(lhs);
00178     result += rhs;   
00179     return result;
00180 }
00181 
00182 
00183 //****************************************************************
00184 //
00185 //  Make these stubs
00186 
00187 const BigInt & BigInt::operator -=(const BigInt & rhs)
00188 // postcondition: returns value of bigint - rhs after subtraction
00189 {
00190 }
00191 
00192 const BigInt & BigInt::operator *=(int num)
00193 // postcondition: returns num * value of BigInt after multiplication
00194 {
00195 }
00196 
00197 BigInt operator *(int num, const BigInt & a)
00198 // postcondition: returns num * a     
00199 {
00200 }
00201 
00202 //****************************************************************
00203 
00204 void BigInt::Print(ostream & os) const
00205 // postcondition: BigInt inserted onto stream os
00206 {
00207     os << ToString();
00208 }
00209 
00210 apstring BigInt::ToString() const
00211 // postcondition: returns string equivalent of BigInt
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 // precondition: INT_MIN <= self <= INT_MAX
00230 // postcondition: returns int equivalent of self
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 // precondition: DBL_MIN <= self <= DLB_MAX
00250 // postcondition: returns double equivalent of self
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 // postcondition: big inserted onto stream out
00267 {
00268     big.Print(out);
00269     return out;
00270 }
00271 
00272 istream & operator >> (istream & in, BigInt & big)
00273 // postcondition: big extracted from in, must be whitespace delimited     
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 // postcondition: returns true if lhs == rhs, else returns false
00283 {
00284     return lhs.Equal(rhs);
00285 }
00286 
00287 bool BigInt::Equal(const BigInt & rhs) const
00288 // postcondition: returns true if self == rhs, else returns false
00289 {
00290 
00291     if (NumDigits() != rhs.NumDigits() || IsNegative() != rhs.IsNegative())
00292     {
00293         return false;
00294     }
00295     // assert: same sign, same number of digits;
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 // postcondition: returns true if lhs != rhs, else returns false     
00309 {
00310     return ! (lhs == rhs);
00311 }
00312 
00313 bool operator < (const BigInt & lhs, const BigInt & rhs)
00314 // postcondition: return true if lhs < rhs, else returns false     
00315 {
00316     return lhs.LessThan(rhs);
00317 }
00318 
00319 bool BigInt::LessThan(const BigInt & rhs) const
00320 // postcondition: return true if self < rhs, else returns false     
00321 {
00322     // if signs aren't equal, self < rhs only if self is negative
00323     
00324     if (IsNegative() != rhs.IsNegative())
00325     {
00326         return IsNegative();         
00327     }
00328 
00329     // if # digits aren't the same must check # digits and sign
00330     
00331     if (NumDigits() != rhs.NumDigits())
00332     {
00333         return (NumDigits() < rhs.NumDigits() && IsPositive()) ||
00334                (NumDigits() > rhs.NumDigits() && IsNegative());
00335     }
00336 
00337     // assert: # digits same, signs the same
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;      // self == rhs
00348 }
00349 
00350 bool operator > (const BigInt & lhs, const BigInt & rhs)
00351 // postcondition: return true if lhs > rhs, else returns false
00352 {
00353     return rhs < lhs;    
00354 }
00355 
00356 bool operator <= (const BigInt & lhs, const BigInt & rhs)
00357 // postcondition: return true if lhs <= rhs, else returns false
00358 {
00359     return lhs == rhs || lhs < rhs;
00360 }
00361 bool operator >= (const BigInt & lhs, const BigInt & rhs)
00362 // postcondition: return true if lhs >= rhs, else returns false
00363 {
00364     return lhs == rhs || lhs > rhs;
00365 }
00366 
00367 void BigInt::Normalize()
00368 // postcondition: all leading zeros removed     
00369 {
00370     int k;
00371     int len = NumDigits();
00372     for(k=len-1; k >= 0; k--)        // find a non-zero digit
00373     {
00374         if (GetDigit(k) != 0) break;
00375         myNumDigits--;               // "chop" off zeros
00376     }
00377     if (k < 0)    // all zeros
00378     {
00379         myNumDigits = 1;
00380         mySign = positive;
00381     }
00382 }
00383 
00384 
00385 
00386 int BigInt::NumDigits() const
00387 // postcondition: returns # digits in BigInt
00388 {
00389     return myNumDigits;
00390 }
00391 
00392 int BigInt::GetDigit(int k) const
00393 // precondition: 0 <= k < NumDigits()
00394 // postcondition: returns k-th digit 
00395 //                (0 if precondition is false)
00396 //                Note: 0th digit is least significant digit
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 // precondition: 0 <= k < NumDigits()
00407 // postcondition: k-th digit changed to value
00408 //                Note: 0th digit is least significant digit
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 // postcondition: value added to BigInt as most significant digit
00422 //                Note: 0th digit is least significant digit     
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 // postcondition: returns true iff BigInt is negative
00434 {
00435     return mySign == negative;
00436 }
00437 
00438 bool BigInt::IsPositive() const
00439 // postcondition: returns true iff BigInt is positive
00440 {
00441         return mySign == positive;
00442 }

Generated at Sun Feb 24 09:56:55 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001