2

I'm developing a class for large number arithmetic, it now knows how to do addition, handle cin and cout.

It, however has very limited and basic subtraction functionality, and does not know how to handle negative. But that can be easily resolved.

My question is this, how to do multiplication.

I will detail how it handle cin and cout here.

For cin, it will save integers to value[500], for example, 50 will be saved to value[498] and value[499]. BUT NOT value[0] and value[1]

For cout, it will scan for the first non-zero value from value[0] to value[499], and then output from that non-zero value to the end. Also, if it finds no non-zero value, it will output 0.

Here's my code:

#include <iostream>

using namespace std;

class largeNumber {
public:
    int value[500];
    largeNumber()
    {
        for ( int i = 0 ; i < 500 ; ++ i )
        {
            value[i] = 0;
        }
    }
    //below are arithmetic operations
    largeNumber operator+(const largeNumber &ln) const
    {
        largeNumber result;
        for ( int i = 0 ; i < 500 ; ++ i )
        {
            result.value[i] = value[i] + ln.value[i];
        }
        for ( int i = 499 ; i >= 0 ; -- i )
        {
            if ( result.value[i] >= 10 )
            {
                result.value[i - 1] += ( result.value[i] / 10 );
                result.value[i] %= 10;
            }
        }
        return result;
    }
    largeNumber operator-(const largeNumber &ln) const
    {
        largeNumber result;

        for ( int i = 0 ; i < 500 ; ++ i )
        {
            result.value[i] = value[i] - ln.value[i];
        }
        for ( int i = 499 ; i >= 0 ; -- i )
        {
            if ( result.value[i] < 0 )
            {
                --result.value[i - 1];
                result.value[i] += 10;
            }
        }
        return result;
    }
    largeNumber operator*(const largeNumber &ln) const
    {
        largeNumber result;
        for ( int x = 499 ; x >= 0 ; -- x )
        {
            for ( int y = 499 ; y >= 0 ; -- y )
            {
                int dx = 499 - x;
                int dy = 499 - y;
                int dr = dx + dy;
                int r = 499 - dr;
                if ( r >= 0 && r <= 499 )
                {
                    result.value[r] = value[x] * ln.value[y];
                }
            }
        }
        for ( int i = 499 ; i >= 0 ; -- i )
        {
            if ( result.value[i] >= 10 )
            {
                result.value[i - 1] += ( result.value[i] / 10 );
                result.value[i] %= 10;
            }
        }
        return result;
    }
    //below are cin, cout operators
    friend ostream& operator<<(ostream& out, const largeNumber& ln)
    {
        bool valueFound = false;
        for ( int i = 0 ; i < 500 ; ++ i )
        {
            if ( ln.value[i] != 0 )
            {
                valueFound = true;
            }
            if ( valueFound == true )
            {
                out << ln.value[i];
            }
        }
        if ( valueFound == false )
        {
            out << "0";
        }
        return out;
    }
    friend istream& operator>>(istream& in, largeNumber& ln) // input
    {
        string str;
        in >> str;
        int length = str.length();
        for ( int i = 500 - length ; i < 500 ; ++ i )
        {
            ln.value[i] = (str[length-(500-i)] - 48);
        }
        return in;
    }
};

int main()
{
    largeNumber a, b;
    string op;
    cin >> a >> op >> b;
    cout << a * b;
    return 0;
}

I've included my way to do multiplication, however it is flawed.

By the way, the number given by teacher promised that the result of multiplication will be a number less than 500 digit.

Chimera
  • 5,884
  • 7
  • 49
  • 81
Shane Hsu
  • 7,937
  • 6
  • 39
  • 63
  • There are already implementations of this, for example http://gmplib.org/. Is there any particular reason for not using one of them? – andand Sep 14 '12 at 18:58
  • 1
    And most bignums are arbitrary size, not just 500*32 bits. – Puppy Sep 14 '12 at 19:02
  • 1
    There is a great reason, it's a homework. So, I kinda need to do it myself and not use third-party library. – Shane Hsu Sep 14 '12 at 19:03
  • [tag:homework] is going away on StackOverflow. I removed it from this question. – Chimera Sep 14 '12 at 19:22
  • In principle, you are already there. Just change assignment = to incrementation += in `result.value[r] += value[x] * ln.value[y];`. This should be all that is needed to make this code correct. – Lutz Lehmann Mar 04 '14 at 21:34
  • You could check in the outer loop if `value[x]==0`, then you do not need to run the inner loop. – Lutz Lehmann Mar 04 '14 at 21:48

1 Answers1

6

Lets start with simple multiplication(Long multiplication):

112 * 301

          1     1     2
          3     0     1
          ______________
          1     1     2
     0    0     0
 3   3    6
 _______________________
 3   3    7     1     2

So, this needs N by N matrix as rows to be added with shifting-n-times.

Where are you doing this addition and where is shifting?

For your question, it would need 500 x 500 multiplications and 500 x 500 additions. O(N*N)

Pro: each digit-multiplication can be done in a single byte so you can change the structure of digits that your compiler can vectorize the code and multiply 16 to 32 digits at once(unrolls quite good).

Con: too many computing(nearly 25-40 iteration per 500 digits-num)

Note: GPU-powered calculus could give it roughly 40x more speed. Such as OpenCL or Cuda.

huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
  • I understand that it will need shifting n times, that means multiplying 2 500-digit number will result in a 999-digit number. That's why my code include a checker that checks if it will write to value[699], which will result in a run-time error. – Shane Hsu Sep 14 '12 at 19:08
  • 1
    There are other algorithms that are significantly more advanced but more efficient (including some that use fast fourier transforms and other complex calculations), but for a first stab at writing a library, it's probably best to stick to the way you did it on paper when you first learned how, as suggested here... – twalberg Sep 14 '12 at 19:09
  • And the teacher promise that he will limit the output of all tests to less than 500. – Shane Hsu Sep 14 '12 at 19:09
  • @twalberg : Fourier Transform for multiplication? Can you give a link please? – huseyin tugrul buyukisik Sep 14 '12 at 19:10
  • If your teacher limits output by 500, then he/she wont give you really 500-digit numbers. Just make your 500*500 calculator then crop the MSB(more significant 250-digit) part. More optimizing: use a secret 250-digit multiplicator :) – huseyin tugrul buyukisik Sep 14 '12 at 19:12
  • 1
    @tuğrulbüyükışık [Wikipedia](http://en.wikipedia.org/wiki/Multiplication_algorithm) details quite a few different algorithms, including Fourier multiplication. – twalberg Sep 14 '12 at 19:13
  • @twalberg This is marked homework. `FFT` is too hard a topic to pursue for a homework. Just saying, :) – Hindol Sep 14 '12 at 19:15
  • 1
    @Hindol Yes, that's why I only mentioned that other methods exist, but suggested the method proposed in the answer (besides, graduate students have homework too...). – twalberg Sep 14 '12 at 19:16
  • @twalberg wikipedia article is very far from a complete description of FFT algorithm and the path to an implemention will be long. Beside, for 16000 bits this would result in a slower algorithm than the naive O(N*N). My guess is that a Karatsuba would be enough for such short integers, it would be interesting to check the thresholds used in gmp. – aka.nice Sep 14 '12 at 19:47
  • @aka.nice Yeah, I guess I shouldn't have said Wikipedia "detailed" the algorithms - it really only summarizes or introduces them... I only mentioned it though because someone else wanted a link to support that the FFT can be used for multiplication... Again, I wasn't suggesting the OP actually attempt to implement that algorithm... – twalberg Sep 14 '12 at 19:57
  • Can anybody give me a sample of FFT for multiplication? – huseyin tugrul buyukisik Sep 14 '12 at 20:00
  • Trust me, you have to be **very hardcore** to want to see an implementation of FFT multiplication. – Mysticial Sep 14 '12 at 20:07
  • I heard FFT used in some signal-processing, compressing algorithms. – huseyin tugrul buyukisik Sep 14 '12 at 20:09
  • This FFT is the integer modular FFT, also called the Schönhage-Strassen multiplication. If you want to study it, there are online-papers by Daniel J. Bernstein called "Fast multiplication for mathematicians" or something like that where the algebraic background is extensively described. – Lutz Lehmann Mar 04 '14 at 21:51