Thread: Calculator Logic

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    28

    Calculator Logic

    I've been trying to build a calculator that gets around the limitations of int variables by splitting the number into smaller chunks. I've gotten the add to work successfully but have not been able to get the multiply logic to follow the same path. It works up to a certain point, but the logic fails when I enter a larger number. For example, entering 80 *120 returns 9600. If I enter a number like 222 * 444, it comes up with is -504. I'm not quite sure how to fix this. Im still pretty weak on vector array's.
    Code:
    /***********************************
    *      Pre-Compiler Directives     *
    ***********************************/
    #include <iostream>                 // cin, cout, >>, <<
    #include <iomanip>                  // setfill()
    #include <vector>                   // vector<T>
    #include <algorithm>                // sort()
    using namespace std;
    
    /***********************************
    *        Global Variables          *
    ***********************************/ 
    typedef vector<short int> BigInt; // short int = type BigInt = what we call the vector
    BigInt int1;
    BigInt int2;
    BigInt answer;
    BigInt x;
    
    /***********************************
    *        Function Definitions      *
    ***********************************/
    void readBig(BigInt & x);
    void printBig(const BigInt & x);
    void add(BigInt int1, BigInt int2, BigInt & answer);
    void multiply(BigInt int1, BigInt int2, BigInt & answer);
     
    
    /***********************************
    *            Main				   *
    ***********************************/
    int main()
    {
       cout << "Enter BigInts in blocks of 3 digits (-1 to stop).\n";
       char option;
       for (;;)
       {
          cout << "\nEnter +, -, *, /, or Q (to quit): ";
          cin >> option;
          if (option == 'Q' || option == 'q') break;
          BigInt int1, int2, answer;
          cout << "Enter first BigInt:  ";
          readBig(int1);
          cout << "Enter second BigInt: ";
          readBig(int2);
          switch (option)
          {
             case '+' : add(int1, int2, answer);
                        break;
             case '*' : multiply(int1, int2, answer);
                        break;
             default  : cerr << "Illegal operation\n";
           }
    	 // cout << "\n" << int1[1];  Accesses the first integer
          cout << "Answer: ";
          printBig(answer);
       }
    }
    
    
    /********************************************
    * readBig reads a BigInt.					*
    *											*
    * Receive:   BigInt x						*
    * Pass back: x with a value input for it	*
    ********************************************/
    
    void readBig(BigInt & x)
    {
    short int block;
       for (;;)
       {
       cin >> block;
       if (block < 0) return;
       x.push_back(block);
       }
     }
    
     
    
    /********************************************
    * printBig displays a BigInt.				*
    *											*
    * Receive: BigInt x							*
    * Output:  x								*
    ********************************************/
    void printBig(const BigInt & x)
    {
      cout << setfill('0');
       for (int i = 0; i < x.size(); i++)
       {
          cout << setw(3) << x[i] << ' ';
          if (i > 0 && i % 20 == 0) cout << endl;
       }
       cout << endl;
    }
    
    
    	
    	
     /*******************************************************
     * 'add' adds two BigInts.								*
     * Receive:    BigInts int1 and int2					*
     * Pass back : int1 + int2								*
     *														*
     *******************************************************/
    
     
    
    void add(BigInt int1, BigInt int2, BigInt & answer)
    // cout << "\n" << int1[1];  Accesses the first integer second element
    {
    	short int first,         // a block of int1
                  second,        // a block of int2
                  result,        // a block in their sum
                  carry = 0;     // the carry in adding two blocks
       int size1 = int1.size(),
           size2 = int2.size(),
           maxSize = (size1 < size2 ? size2 : size1);
    
    	reverse(int1.begin(), int1.end());
        reverse(int2.begin(), int2.end());
    	for (int i = 0; i < maxSize; i++)
       {
          if (i < size1)
             first = int1[i];
          else
             first = 0;
          if (i < size2)
             second = int2[i];
          else
             second = 0;
          short int temp = first + second + carry;
    	  cout << temp << endl; // For logic debugging
          result = temp % 1000;
          carry = temp / 1000;
          answer.push_back(result);
       }
       if (carry > 0)
          answer.push_back(carry);
       reverse(answer.begin(), answer.end());
    }
    	
    
    void multiply(BigInt int1, BigInt int2, BigInt & answer)
    {
    	short int first,         // a block of int1
                  second,        // a block of int2
                  result,        // a block in their sum
                  carry = 0;     // the carry in multiplying two blocks
       int size1 = int1.size(),
           size2 = int2.size(),
           maxSize = (size1 < size2 ? size2 : size1);
    
    	reverse(int1.begin(), int1.end());
        reverse(int2.begin(), int2.end());
    	for (int i = 0; i < maxSize; i++)
       {
          if (i < size1)
             first = int1[i];
          else
             first = 0;
          if (i < size2)
             second = int2[i];
          else
             second = 0;
          short int temp = (first * second) + carry;
    	  cout << temp << endl; // For logic debugging
          result = temp % 1000;
          carry = temp / 1000;
          answer.push_back(result);
       }
       if (carry > 0)
          answer.push_back(carry);
       reverse(answer.begin(), answer.end());
    }
    Last edited by kryonik; 08-22-2006 at 12:48 PM.

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    >> option == 'Q' || option == 'q'

    You could use toupper(option) == 'Q' or something


    Will you give an example input which fails?

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > result = temp % 1000;
    If each 'digit' of your bignum is between 0 and 1000.

    Your algorithm seems OK, you just need to be careful about limiting the range of values stored in each element of your vector.

    I've done this in the past with arrays of char, where each char stores just one decimal digit 0..9, whose multiply result is always <100
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Aug 2005
    Posts
    28
    Quote Originally Posted by twomers
    >> option == 'Q' || option == 'q'

    You could use toupper(option) == 'Q' or something


    Will you give an example input which fails?
    I can put in 80 * 120 and get 9600.

    If I put in 222 * 444 I get a -504.

    Thats where the logic fails and I'm not sure why.

  5. #5
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    If short is 2 bytes, it can only keep up to (2 powered by 15) if it is signed.
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

Popular pages Recent additions subscribe to a feed