Ricky Sterling Ricky Sterling - 1 month ago 21
Java Question

Finding A power B using BigInteger and using recursion

This is the piece of code in Java.

import java.util.Scanner;

import java.math.*;

class power1 {

public static void main(String[] args) {

Scanner in=new Scanner(System.in);
long a=in.nextLong();
BigInteger b=in.nextBigInteger();
long res=power(a,b);
System.out.println(res);
}

public static long power(long x,BigInteger n) {

int b=(int)(Math.pow(10,9)+7);
long m;
if (n.compareTo(BigInteger.ZERO)==0)
return 1;
if(n.compareTo(BigInteger.ONE)==0)
return x;
if ((n.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO)==0))
{
m = power(x,n.divide(BigInteger.valueOf(2)));
return (m * m)%b;
}
else return (x * power(x,n.subtract(BigInteger.valueOf(1)))%b);

}

}


This is should work for any value of b considering that its a BigInteger.
But when i enter very large value of b ,i get errors as

Exception in thread "main" java.lang.StackOverflowError
at java.math.MutableBigInteger.divideKnuth(Unknown Source)
at java.math.MutableBigInteger.divideKnuth(Unknown Source)
at java.math.BigInteger.remainderKnuth(Unknown Source)
at java.math.BigInteger.remainder(Unknown Source)
at java.math.BigInteger.mod(Unknown Source)


Is there a way to fix it?

Answer

You should implement the following algorithm:

recursivePower(base, exp):
    if (exp == 0) 
        return 1;
    if (exp == 1)
        return base;
    if (exp%2 == 0) {
        temp = recursivePower(base, exp/2);
        return temp*temp;
    temp = recursivePower(base, (exp-1)/2);
    return temp*temp*base;

This will drastically reduce the number of calls you're using. Another thing is enlarging the size of the stack. Run your application with java Test -Xss2048k - try different sizes.

And last but not the least use BigInteger all the time.

public static BigInteger recursivePower (BigInteger base, BigInteger exp) {
    if (exp.compareTo(BigInteger.ZERO) == 0) 
        return BigInteger.ONE;
    if (exp.compareTo(BigInteger.ONE) == 0)
        return base;
    if (exp.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
        BigInteger temp = recursivePower(base, exp.divide(BigInteger.valueOf(2)));
        return temp.multiply(temp);
    }
    BigInteger temp = recursivePower(base, (exp.subtract(BigInteger.valueOf(1)).divide(BigInteger.valueOf(2))));
    return temp.multiply(temp).multiply(base);
}

public static void main(String []args){
    System.out.println(recursivePower(BigInteger.valueOf(2), BigInteger.valueOf(80)).toString());
 }