/* In this project we created a class which represents a big integer value. "Big" means, it can hold arbitrary number of digits. We defined the basic operations on that class (operator= and operator+). The class seems to work correctly. However we have serious efficiency problems. It seems, that operations in main() are terrible slow, and even worse: execution time is non-linear with the number of digits. Try to detect the bottlenecks, and fix they (in iterative steps). */ #include <stdio.h> #include <string.h> #include <time.h> class BigInt { friend class DigitStream; public: BigInt(const char*); BigInt(unsigned n = 0); BigInt(const BigInt&); ~BigInt() { delete [] digits; } void operator=(const BigInt&); BigInt operator+(const BigInt&) const; void print(FILE* f = stdout) const; private: char* digits; unsigned ndigits; BigInt(char* d, unsigned n) { digits = d; ndigits = n; } }; class DigitStream { public: DigitStream(const BigInt& n) { dp = n.digits; nd = n.ndigits; } unsigned operator++() { if ( nd == 0 ) return 0; else { nd--; return *dp++; } } private: char* dp; unsigned nd; }; void BigInt::print(FILE* f) const { for (int i = ndigits-1; i>=0; i--) fprintf(f, "%c", digits[i]+'0'); } void BigInt::operator=(const BigInt& n) { if (this == &n) return; delete [] digits; unsigned i = n.ndigits; digits = new char[ndigits = i]; char* p = digits; char* q = n.digits; while(i--) *p++ = *q++; } BigInt BigInt::operator+(const BigInt& n) const { unsigned maxDigits = (ndigits>n.ndigits ? ndigits : n.ndigits)+1; char* sumPtr = new char[maxDigits]; BigInt sum(sumPtr, maxDigits); DigitStream a(*this); DigitStream b(n); unsigned i = maxDigits; unsigned carry = 0; while (i--) { *sumPtr = (++a) + (++b) + carry; if ( *sumPtr >= 10 ) { carry = 1; *sumPtr -= 10; } else carry = 0; sumPtr++; } return sum; } BigInt::BigInt(unsigned n) { char d[3*sizeof(unsigned)+1]; char* dp = d; ndigits = 0; do { *dp++ = n%10; n /= 10; ndigits++; } while (n > 0); digits = new char[ndigits]; for (register i = 0; i < ndigits; i++) digits[i] = d[i]; } BigInt::BigInt(const BigInt& n) { unsigned i = n.ndigits; digits = new char[ndigits = i]; char* p = digits; char* q = n.digits; while (i--) *p++ = *q++; } BigInt::BigInt(const char* digitString) { unsigned n = strlen(digitString); if (n != 0) { digits = new char[ndigits = n]; char* p = digits; const char* q = &digitString[n]; while (n--) *p++ = *--q - '0'; } else { digits = new char[ndigits = 1]; digits[0] = 0; } } int main() { BigInt b = 1; time_t t1 = time(NULL); for (int i = 1; i <= 50000; ++i) b = b + 1; time_t t2 = time(NULL); printf("Elapsed time: %ld\n", t2 - t1); // 1000 rec = 1 sec // 2000 rec = 7 sec // 5000 rec = 38 sec // 10000 rec = 150 sec // ... on my old machine :-) }