Search code examples
javaalgorithmmathexponentiation

Return a large power (mod 2^32)


I need to work out a very large power modulo (2^32), i.e. I want the result of:

y = (p^n) mod (2^32)

p is a prime number
n is a large integer

Is there a trick to doing this efficiently in Java?

Or am I stuck with doing it in a loop with n iterations?


Solution

  • The simple way to mod 2^32 is to use & 0xFFFFFFFFL. Also, there happens to be a type which naturally keeps the lowest 32-bit called int ;) If you use that you don't even need to perform the & until you have the result (so the answer is unsigned) For this reason you only need to keep the last 32 bit of the answer. To speed up the ^n you can calculate the square, it's square and it's square etc, e.g if n is 0b11111 then you need to multiply p^16 * p^8 * p^4 * p^2 * p.

    In short, you can use plain int as you only need 32-bit of accuracy and values with a cost of O(ln n) where n is the power.

    int prime = 2106945901;
    for (int i = 0; i < 10; i++) {
        long start = System.nanoTime();
        long answer1 = BigInteger.valueOf(prime)
                                 .modPow(
                                     BigInteger.valueOf(prime), 
                                     BigInteger.valueOf(2).pow(32)).longValue();
    
        long mid = System.nanoTime();
        int answer2 = 1;
        int p = prime;
        for (int n = prime; n > 0; n >>>= 1) {
            if ((n & 1) != 0)
                answer2 *= p;
            p *= p;
        }
        long end = System.nanoTime();
        System.out.printf("True answer %,d took %.3f ms, quick answer %,d took %.3f ms%n",
                answer1, (mid - start) / 1e6, answer2 & 0xFFFFFFFFL, (end - mid) / 1e6);
    }
    

    prints finally

    True answer 4,169,684,317 took 0.233 ms, quick answer 4,169,684,317 took 0.002 ms