# Calculator Logic

• 08-22-2006
kryonik
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()); }```
• 08-22-2006
twomers
>> option == 'Q' || option == 'q'

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

Will you give an example input which fails?
• 08-22-2006
Salem
> 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
• 08-22-2006
kryonik
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.
• 08-22-2006
siavoshkc
If short is 2 bytes, it can only keep up to (2 powered by 15) if it is signed.