Reputation: 55
I'm trying to complete an assignment for my Java class where we are to create an efficient method for solving powers (taking a base to an exponent, defined by user's input).
I have just about everything in place, but the efficient method pow2
isn't handling odd exponents correctly. It multiplies the base by one more than it's supposed to. What am I missing here?
For instance, if I input 4 as my base and 5 as my exp, the program will spit out 4096 instead of 1024.
import java.util.Scanner;
public class MyPow {
public static int countGbl = 0;
public static double raise(double base, int exp) {
double b = base;
for (int i = 1; i < exp; i++){
countGbl += 1;
base = base * b;
}
return base;
}
public static double pow1(double base, int exp) {
if (base == 0.0) return Double.POSITIVE_INFINITY;
else if (base == 0.0 && exp >= 0) return 0.0;
else if (exp == 1) return base;
else if (base > 0 && exp == 0) return 1.0;
else{
if (exp < 0){
base = 1.0/base;
exp = -exp;
}
if (exp % 2 == 0){
countGbl++;
return pow1(base, exp/2) * pow1(base, exp/2);
}
else {
countGbl += 2;
return pow1(base, exp/2) * pow1(base, exp/2) * base;
}
}
}
public static double pow2(double base, int exp) {
double temp = raise(base, exp/2);
double retval = temp*temp;
if (exp % 2 == 1){
countGbl++;
retval *= temp;
}
return retval;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter base: ");
double base = Integer.parseInt(s.nextLine());
System.out.println("Enter exp: ");
int exp = Integer.parseInt(s.nextLine());
System.out.println(pow2(base, exp));
System.out.println(countGbl);
}
}
Just an FYI, the reason for the pow1
method is because we are to write an example method that isn't as efficient as pow2
.
Also, please ignore countGbl
. Our professor wants us to count the number of multiplications done during the method calls.
Upvotes: 1
Views: 767
Reputation: 1227
I sketched this recursive solution to your problem, where odds and even exponents are treated directly into raise
:
public static double raise(double base, int exp) {
if (exp == 0) {
return 1;
} if ((exp % 2) == 1) {
countGbl += 1;
return raise(base, exp-1) * base;
} else {
double tmp = raise(base, exp/2);
countGbl += 1;
return tmp * tmp;
}
}
public static double pow2(double base, int exp) {
return raise(base, exp);
}
Here the number of multiplications is logarithmic with respect to exp.
Upvotes: 1
Reputation: 178253
It looks like you are attempting to make the optimization:
baseexp = baseexp/2 * baseexp/2 * base
where exp
is odd, and where exp/2
is Java's integer division, really also a floor function in math.
However, what you are doing in the odd case is multiplying in another factor of temp
, which is already calculated to be baseexp/2.
Multiply retVal
by base
, not temp
. Change in pow2
retval *= temp;
to
retval *= base;
Additionally, another optimization would be instead of going back to the raise
method after dividing exp
by 2 in pow2
, you can keep going with recursion, repeatedly calling pow2
until you reach a base case of an exponent of 1 or 0.
Upvotes: 2