-4

can someone explain how to let operations like 3^9999 work in c++, as i found, if number is too long it causes problems. I've heard that there is a way to work it out. (Please do not suggest any external libraries)

bla2e
  • 47
  • 8
  • 1
    If `^` means exponentiation, you need a big-integer library. If you don't want to use an external library, you have to write your own. – Daniel Fischer Sep 05 '12 at 18:16
  • although I won't suggest you use a big number library, you could look at the code they use? – Jimmy Sep 05 '12 at 18:17
  • 9
    When the best solution is to use an external library, but people ask for no suggestions of external libraries, do you know what the solution becomes? *Implement on your own what was already implement in an external library*. – R. Martinho Fernandes Sep 05 '12 at 18:18
  • 1
    Nonsense question. Standard function `double pow( double base, double exponent);` from gives me 5.4378339511420862476775224306038e+4770. – Öö Tiib Sep 05 '12 at 18:22
  • 1
    @ÖöTiib I'm *guessing* since the OP bothered to ask the question, they want all the digits, though. Why the "do not suggest any external libraries" is beyond me though, (and smells a little of homework?) – lc. Sep 05 '12 at 18:24
  • 1
    @Ic makes sense. Probably someone down-voted it because we have to guess. – Öö Tiib Sep 05 '12 at 18:26
  • it was asked on olympiad when i was at high school, i couldn't solve it and still wondering how to solve it :) The only suggestion i have is to place the result into array (that is what told the guy who solved it) – bla2e Sep 05 '12 at 18:27
  • The units digit is 1. The rest is left as an exercise. :-) – Happy Green Kid Naps Sep 05 '12 at 18:48
  • @ÖöTiib, a standard double can't go beyond 1.8e+308 [according to Wikipedia](http://en.wikipedia.org/wiki/IEEE_754-1985). What version of C++ are you using? – Mark Ransom Sep 05 '12 at 18:53
  • @Mark Ransom the C++ standard does not certainly specify that. Seems that mine is using 80 bit doubles (x86 extended precision format). – Öö Tiib Sep 05 '12 at 19:06
  • 1
    @HappyGreenKidNaps Nope, the units digit is 7 (3^4 % 10 = 1, 9999 % 4 = 3, 3^3 % 10 = 7). – Daniel Fischer Sep 05 '12 at 19:44
  • @DanielFischer -- Mea culpa. I was thinking of 3^10000. – Happy Green Kid Naps Sep 05 '12 at 20:42

4 Answers4

2

Split your problem into three problems.

1) First make solution how to multiply very long integers.

2) turn 9999 into binary 10011100001111. There are 14 bits. 8 bits are set. Set bits (in order from end) mean that 9999 = 1 + 2 + 4 + 8 + 256 + 512 + 1024 + 8192. The factors are useful since 3^2 = 3^1 * 3^1 etc. in general n^(2^m) = n^(2^(m-1)) * n^(2^(m-1)). You can calculate the factors in cycle starting from 3^1 = 3, that makes 13 multiplications.

3) Calculate 3^9999 = 3^1 * 3^2 * 3^4 * 3^8 * 3^256 * 3^512 * 3^1024 * 3^8192 by multiplying the factors into result. That makes 7 more multiplications.

For calculating 3^9999 you need 20 very long integer multiplications.

Öö Tiib
  • 10,809
  • 25
  • 44
  • Very elegant solution, but it is beyond of my abilities – bla2e Sep 05 '12 at 19:10
  • It took me a minute to realize the optimization versus my own answer - `3^2=3^1*3^1`, `3^4=3^2*3^2` etc. You have 12 multiplications to get the factors `3^1` to `3^(2^13)` and 7 more to multiply the 8 required factors. – Mark Ransom Sep 05 '12 at 21:27
1

Since you have asked for a solution that doesn't rely on a library, you'll have to do it the hard way.

Create a function that multiplies two arrays of digits together. You'll need about log10(3)*9999 digits for this, or 4771. Initialize two arrays with all zeros and a 3, then multiply the first by the second for 9998 times.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • so, i'll have 2 arry, and then multiply them... 1) why one of them should be all 0 and another all 3? and where i should store the result? – bla2e Sep 05 '12 at 18:29
  • @bla2e, what I meant was to start both arrays with 4770 zeros and a single 3 at the end. Do the multiply in place so that the result is in one of the two arrays. – Mark Ransom Sep 05 '12 at 18:38
1

Hope you're not looking for optimisation...

int N = 9998;
int M = 5000;
int arr [M];

for ( int j = 0 ; j < M ; ++j )
        arr[j]=0;

arr[M-1] = 3;


for ( int i = 0 ; i < N ; ++i ) {

        for ( int j = 0 ; j < M ; ++j )
                arr[j] = arr[j]*3;

        for ( int j = M-1 ; j > 0 ; --j ) {
                arr[j-1] = arr[j-1] + arr[j]/10;
                arr[j] = arr[j]% 10;
        }
}


for ( int j = 0 ; j < M ; ++j )
        std::cout << arr[j];
Arthur
  • 1,974
  • 2
  • 21
  • 28
0

Any ideas on how I could make it uglier so his professor won't accept it? =]

#include <stdio.h>
#include <string.h>
int main()
{
    unsigned char ds[9999];
    unsigned char c;
    ds[0] = 3;
    bzero(ds+1, 9998);
    for(int p = 2; p <= 9999; p++)
    {
        c = 0;
        for(int d=0; d<p/2+1; d++)
        {
            ds[d] = ds[d] * 3 + c;
            c = ds[d] / 10;
            ds[d] = ds[d] % 10;
        }
    }
    int d = 9998;
    for(; d>=0; d--)
        if(ds[d] != 0)
            break;
    for(; d>=0; d--)
        printf("%d", ds[d]);
    printf("\n");
}
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
Sniggerfardimungus
  • 11,583
  • 10
  • 52
  • 97
  • there is no professor, just my own curiosity, so u're free to make it as ugly as you wish :) – bla2e Sep 05 '12 at 19:29