I think a big difficulty for you is caused by storing the most significant digits first in the array.
Doing so may make displaying the number a little easier, but it makes all the arithmetic operations harder to work out. You seem to have made it work for addition, where only one more digit can result, but for multiplication the number of digits add, making your backwards approach harder to manage. If you store the ones digit in Array[0], the 10s digit in Array[1] and so on then the digits remain aligned as to element number and also more digits can be added to the end of the array as your safearray grows.
Use a temp. instance of a bigInt in your multiply function to place the products into so as not to overwrite the very values you're multiplying by.
Why the global
int size = 100;
at line 61? You're using it in places where arr->get_size() should be. Was this necessary to make addition work?
It causes other issues too. Your safearray has a default 10 elements, but your bigInt constructor uses the size=100 figure.
Every time
arr->set(i,0);
is called on line 72 after i=9 a new array is allocated.
This bigInt constructor is causing a new array allocation and copy operation 90 times!
That said,
@fg109 In case you're interested...
I too have written a bigInt class based on a doubly linked list.
I was able to make operators += and -= work without using a temp bigInt because I can overwrite the digit values right away. They aren't needed for further addition calcs.
Not so with multiplication. When doing it the grammar school by hand method each digit is used multiple times.
Since a temp instance was needed I wrote the primary code in operator* and returned the temp instance, then wrote operator*= in terms of operator*.
Most unsatisfactory!
I found I could avoid the temp instance and multiply 2 bigInts in place if I start with the most significant digit of *this and work backwards. I can finish with each digit value in one shot.
I have my digits stored with the least significant in the head node, though it isn't necessary in a doubly linked list. It's just leftover from my treatment in a singly linked list, which I changed from because reverse iteration is useful for display(), compare() and divide().
That's why you'll see push_back() where you push_front().
I'm using int32_t and int64_t types because I'm storing 8 digits per node (base = 100,000,000). Gotta be careful about overflow when multiplying!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
// multiply in place. No temp instance
bigInt& bigInt::operator*=( const bigInt& B )
{
if( B.numNodes == 1 )
{
this->operator*=(B.head->x);// use simpler *= int operation
return *this;
}
// B is multinodal
int64_t product = tail->x;
product *= B.head->x;
int32_t carry = product/base;
int32_t Aval = tail->x;// save
tail->x = product%base;
dnode* itA = tail;
const dnode* itB = nullptr;
// allocate all new nodes on 1st pass
for( itB = B.head->next; itB; itB = itB->next )
{
product = Aval;
product *= itB->x;
product += carry;
push_back( product%base );
carry = product/base;
}
if( carry ) push_back( carry );
// *this is now populated. Carry out remaining passes
for( itA = itA->prev; itA; itA = itA->prev )
{
carry = 0;
Aval = itA->x;// save
itA->x = 0;
dnode* it = itA;
for( itB = B.head; itB; itB = itB->next, it = it->next )
{
product = Aval;
product *= itB->x;
product += carry;
product += it->x;
it->x = product%base;
carry = product/base;
}
if( carry && it ) it->x += carry;
}
isPositive = isPositive ? B.isPositive : !B.isPositive;// !XOR
return *this;
}
|
Now operator* can be what it should:
1 2 3 4 5 6
|
bigInt operator*( const bigInt& a, const bigInt& b )
{
bigInt temp(a);
temp *= b;
return temp;
}
|
Have you tried operators / or % yet?
I based mine on the "by hand" long division method. It was tricky, but it seems to be working.