Topic description
- Given a float base of type double and an integer exponent of type int. Find the exponent power of base.
- Address: Niu Ke Link
Solution
- This is a very classic bit operation problem
- First, this is a question with a lot of special cases:
- When the index is 0, return 1 directly
- The base is 0, but when the exponent is negative, a division by 0 exception occurs, and when the exponent is positive, 0 is returned;
- Other cases (use the following three methods)
- Method 1: After judging the boundary conditions, loop directly. If the absolute value of the index is n, then the time complexity of this method is O(n)
Method 2: Use the idea of fast power , for example, to find 3^11, then the binary of index 11 is 1011. For 1011, from right to left, each bit corresponds to 1, 2, 4, 8. And 3^11 = 3^(1011) = 3^(1000 + 0010 + 0001) = 3^8 * 3^2 + 3^1 . So we can look at it this way, 1011 corresponds to 3, 3^2, 3^4, 3^8 from right to left , which is a doubling relationship. Therefore, as long as we get each digit
of the binary bit by bit of the exponent , see whether the current bit is 1 or 0. If it is 1, it will be multiplied into res, and doubled in each bit-by-bit process , 3, 3^ 2, 3^4, 3^8. So how do you get each digit of the binary bit by bit? Using left shift >> and &, &1 can get the value of the lowest digit, and then the current number >> can get the number on the next digit until it becomes 0.Time Complexity: O(log N)
Method 3: Recursion . 3^11 = 3^5 * 3^5 3 3^10 = 3^5 3^5. So first judge the parity of the exponent
- If odd: f(base, exp) = f(base, exp > >1) * f(base, exp > >1) * base
- If even: f(base, exp) = f(base, exp > >1) * f(base, exp >> 1)
Time complexity: O(log N)
lessons learned
- Use of fast powers
- How to use >> and &1 to get each bit of a number in binary form
- Any number greater than or equal to 1 can be obtained by adding 1, 2, 4, 8, 16, 32... The last digit in binary must be 1. So you can use n & 1 != 0 to judge the parity of n. Note that when using n % 2 != 0 to judge parity, it must be followed by != 0, not! = 1, because for negative numbers, such as -1, the remainder is -1, but it is still an odd number.
- n >> 1 achieves the effect of dividing by 2, of course, this is for positive numbers, and negative numbers will be shifted to the right with a sign
- Calculate 2^n, that is, 1 << n, and others can be solved by fast power.
- The code must be read often, this is a very classic topic of bit operation
Code:
- Method 2:
public double Power(double base, int exponent) {
//指数为0
if (exponent == 0) {
return 1.0;
}
if (base - 0.0 == 0.00001 || base - 0.0 == -0.00001) {
//底为0,指数为负数
if (exponent < 0) {
throw new RuntimeException("除0异常");
}else{ //底为0,指数为正数
return 0.0;
}
}
//先按正指数算
int e = exponent > 0 ? exponent: -exponent;
double res = 1;
//快速幂
while (e != 0) {
//根据当前位是1还是0决定累乘还是不累乘
res = (e & 1) != 0 ? res * base : res;
//翻倍
base *= base;
//右移,迭代
e = e >> 1;
}
//根据指数正负,返回
return exponent > 0 ? res : 1/res;
}
- Method 3:
public double Power(double base, int exponent) {
if (exponent == 0) {
return 1.0;
}
if (base - 0.0 == 0.00001 || base - 0.0 == -0.00001 ) {
if (exponent < 0) {
throw new RuntimeException("除0异常");
}else{
return 0.0;
}
}
return exponent > 0 ? getPower(base, exponent) : 1/getPower(base, -exponent);
}
//传入的e肯定是正数
public static double getPower(double base, int e) {
//base case
if (e == 1) {
return base;
}
//递归计算 f(base,e >> 1)
double halfPower = getPower(base, e >> 1);
//根据指数的奇偶计算 f(base,e)
return (e & 1) != 0 ? base * halfPower * halfPower : halfPower * halfPower;
}