You need to think about how to multiply stuff by hand. For example:
234
x 79
?????
This breaks down into two smaller problems:
234 234
x 9 x 70
???? + ????0
You need a function that multiplies a big number by a single 'big digit' (an int) and
adds the result into a target big number.
Then you can use it to multiply two big numbers:
1 2 3 4 5 6 7 8 9 10 11
|
typedef vector<int> big_number;
void big_multiply_by_int_and_add(
const big_number& a, // source
int b, // source
big_number& d, // destination
int offset_into_d ) // offset into destination
{
// PSEUDOCODE!
d += (a * b) shifted 'offset_into_d' big digits into d;
}
|
Once you have that, you can write a function that multiplies any two big numbers:
1 2 3 4 5 6 7 8 9 10
|
big_number big_multiply( const big_number& a, const big_number& b )
{
big_number d = 0;
int offset_into_d = 0;
for each digit in b (starting with the least-significant big digit)
{
big_multiply_by_int_and_add( a, digit_from_b, d, offset_into_d++ );
}
return d;
}
|
The tricky part is in the first function, making sure to multiply and handle carries correctly: an int * int --> long long int!
For example:
1 2 3 4
|
long long int mult_int( int a, int b )
{
return (unsigned long long int)a * (long long int)b;
}
|
That gives you
two 'digits' worth of information:
1 2 3
|
long long int x = mult_int( a, b );
int xhigh = x >> (sizeof int * 8);
int xlow = (unsigned long long int)x & (unsigned int)(-1);
|
Remember, for normal (power of ten) digits:
3*9=27 → high=2, low=7
It works the same way for big digits. (The only difference is that there are UINT_MAX symbols per 'big digit' instead of the ten symbols for our normal digits.)
Before I go, a couple of other things to observe:
(1)
You should be using an unsigned int for your big digits:
typedef vector<unsigned int> big_number;
This saves you a whole lot of grief. You should adjust the examples above so that
everything is unsigned.
For negative numbers, you only need an extra value somewhere to indicate that it is negative.
I personally find it useful to make a separate class:
1 2 3 4 5 6
|
struct big_number
{
vector <unsigned> digits;
bool is_signed;
...
};
|
But you can easily just have an extra digit in there somewhere that is 0 or 1 for positive and negative. The trick is to remember that it is not part of the number proper and exclude it from the multiplication and addition routines except to note the signedness of the numbers.
(2)
The
order in which you store digits is also important. I personally prefer to store least-significant digits first in the vector; I find it makes indexing stuff a whole lot more natural.
1234
gets stored as:
{ 4, 3, 2, 1 }
Ultimately, however, it is up to you how you wish to store it -- just as long as you are consistent.
Hope this helps.