Valhalla Legends Forums Archive | General Programming | Huge Powers

AuthorMessageTime
R.a.B.B.i.T
I need to find a fairly effecient method of calculating huge powers of huge numbers (power and number both being out to 7 or 8 places).  C/C++/ASM/Java is preferred, although I could possibly do it in other languages.  Any idea on how I could go about doing this (without using an array)?
May 13, 2005, 4:02 PM
Adron
[quote author=rabbit link=topic=11578.msg112343#msg112343 date=1116000136]
I need to find a fairly effecient method of calculating huge powers of huge numbers (power and number both being out to 7 or 8 places).  C/C++/ASM/Java is preferred, although I could possibly do it in other languages.  Any idea on how I could go about doing this (without using an array)?
[/quote]

If that's what you want to do, and you want an exact answer, you will be using an array or a ready-made library that uses an array. There is no native support for such numbers.
May 13, 2005, 4:28 PM
R.a.B.B.i.T
Gah, I was hoping it could be done without one, but if it can't, how should I start?
May 13, 2005, 5:01 PM
Kp
If you really care about speed, go with an assembly implementation (either find one or write one).  Unless you're writing something designed to do huge amounts of big number cryptography, I doubt you really need the extra speed up an assembly implementation can give you.  If you want to use something ready made, java.math.BigInteger or find one of the dozens of C/C++ libraries (vlong, OpenSSL's BN, GNU MP all come to mind).
May 13, 2005, 10:13 PM
R.a.B.B.i.T
Eh, it depends on the speed gain, but whatever.  My CS teacher asked me if I could create a [somewhat] quick program to do this.  He said he made one but it took hours to do one calculation (I think he raised x-billion to the power of x-trillion or something).  Thanks for the help
May 14, 2005, 1:01 AM
Adron
It definitely shouldn't take hours to do.
May 14, 2005, 2:50 AM
Yoni
[quote author=rabbit link=topic=11578.msg112385#msg112385 date=1116032496]
Eh, it depends on the speed gain, but whatever. My CS teacher asked me if I could create a [somewhat] quick program to do this. He said he made one but it took hours to do one calculation (I think he raised x-billion to the power of x-trillion or something). Thanks for the help
[/quote]
Consider that the trivial algorithm for calculating a^b for very long a, b has time complexity O(b log a), while a slightly more thoughtful algorithm has time complexity O((log a)(log b)). (Logs are base 2 inside big O.) With the input numbers your teacher tried, the trivial algorithm requires an amount of operations in the hundreds of trillions, and the better one requires only several thousand ones.

Are you in high school or beyond? Either way (but especially in the former), CS teachers aren't always that bright :P
May 14, 2005, 2:59 AM
R.a.B.B.i.T
High school, but my teacher is one of those guys whose first programming language was punch cards :)

Also, I have no idea what O() is.
May 14, 2005, 3:34 AM
K
[quote author=rabbit link=topic=11578.msg112401#msg112401 date=1116041656]
High school, but my teacher is one of those guys whose first programming language was punch cards :)

Also, I have no idea what O() is.
[/quote]

O(x) means the execution time of a function is less than or equal to x  It's used to describe the order of magnitude of a function.  For example:
[code]
void func(int n)
{
  for(i = 0; i < n; ++n)
      for(j = 0; j < n; ++n)
        feh;
}[/code]
has O(n^2), because the time taken to execute the function is (some constant for the instructions) times n squared.  A binary search has O(log_2(n)), because execution time is the logarithm base 2 of the number of nodes times some constant for the time of the instructions.

Big O Notation
May 14, 2005, 7:16 AM
Yoni
Here are both algorithms. I assume that b is a positive integer. If b is not a positive integer, something different needs to be done.

The slow, obvious one:

1) Multiply a by itself, b times. The result is a^b.

This one has time complexity O(b log a), because the multiplication by a is O(log a) and it is performed b times. Usually the multiplication is expressed as O(1) - but that is wrong, because a can be very long, and the multiplication requires an amount of work in linear correspondence with the amount of digits in "a".

The much faster one:

1) r = a            // r means "result"
2) While b > 1:

2.1) If b is even:
2.1.1) r = r*r
2.1.2) b = b/2

2.2) Else (if b is odd):
2.2.1) r = r*a
2.2.2) b = b - 1

3) return r

Take a few minutes and try to understand why that works and why it is much faster. This is the O((log a)(log b)) one and should not take hours on such small numbers as billions and trillions.
May 14, 2005, 12:25 PM
R.a.B.B.i.T
I've constructed a function based off of that, but it doesn't work (testing 5 to 3 and 5 to 4 both give 625, so something is wrong).
[code]__int64 dealy(__int64 a, __int64 b)
{
    __int64 r = a;
    printf("Calculating,,,\n");

    while(b > 1)
    {
        if(b % 2 == 0)
        {
            r *= r;
            b /= 2;
        }else if(b % 2 == 1) {
            r *= a;
            b--;
        }
    }

    return r;
}[/code]

On top of that, using large numbers (such as 10000000 to 10000000) yeilds 0 because I'm not using a  type which has enough room for the values, so I don't exactly know what to use.
May 14, 2005, 6:15 PM
Arta
As an aside, using mod there will slow you down a lot. You can test for even/odd with a bitwise and:

[code]
if(n & 1)
  // odd
else
  // even
[/code]
May 14, 2005, 6:40 PM
Yoni
Ack... The algorithm I illustrated was totally wrong. I tried to change it from recursive to iterative and didn't stop to make sure what I was doing was correct. Sorry :P

This (mixture of iterative and recursive) algorithm definitely works, with the same time complexity as I explained above (also logarithmic memory complexity now - I guess that can't be avoided):

Power(a, b):      // b is a positive integer

1. While b > 1:

1.1. If b is even:
1.1.1. a = a * a
1.1.2. b = b / 2

1.2. Else (if b is odd):
1.2.1. t = Power(a, (b-1)/2)
1.2.2. Return a*t*t

2. Return a
May 14, 2005, 11:32 PM
R.a.B.B.i.T
That is faring a little better, but even still, the returns top out at x ** 31 (2 ** 31 ==-2147483648, 31 ** 31 == -2010103841, and the such), they simply start rolling over to negatives then to 0.  Using unsigned __int64 does not resolve this issue, and I am still at a loss.
May 15, 2005, 12:35 AM
Arta
If you want to store bigger numbers than will fit into 64 bits, you need a bigint library. Kp posted some links earlier.
May 15, 2005, 12:37 AM
Adron
[quote author=rabbit link=topic=11578.msg112482#msg112482 date=1116117348]
That is faring a little better, but even still, the returns top out at x ** 31 (2 ** 31 ==-2147483648, 31 ** 31 == -2010103841, and the such), they simply start rolling over to negatives then to 0.  Using unsigned __int64 does not resolve this issue, and I am still at a loss.
[/quote]

You need to have big numbers. If you take a ready-made library, it will most likely come with a powers algorithm that works for huge powers. Otherwise you need to implement the operations used by the algorithm Yoni described. I think of the algorithm like this:

integer Power(integer a, integer b)
{
  integer result, factor;
  for(result = 1, factor = a; b > 0; factor = factor * factor, b >>= 1) {
      if(b & 1) result = result * factor;
  }
  return result;
}
May 15, 2005, 2:22 AM
R.a.B.B.i.T
I'll have a look at the libraries, and see what I can understand of them.  As for Adron's implementation: it's 1/3 the length of mine...guess that shows how well I know what I'm doing...
May 15, 2005, 3:30 PM

Search