剑指OFFER笔记_16_数值的整数次方_JAVA实现
题目:数值的整数次方
- 实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
解题思路
- 此题让我们自己去实现一个库函数,常规状态下的输入是很简单的,关键的地方在于处理好各种特殊情况。
- 底数为0。这种情况是没有数学意义的,可以自行设置返回值,只要能够提出此处情况是无意义的就行。
- 指数为0。这种情况下底数为任何值都是1。
- 指数为负数。这种情况下,需要先将指数转换为正数,然后进行常规的操作,最后对结果取倒数。
- 出于效率考虑,我们可以将2^16这种问题转换为(2^8)^2,这样就可以减少很多次运算。
- 此外除法的效率远低于移位操作,可以用>>右移操作来代替除以2。此时对应的对2取余操作也用位与运算来代替(n & 1)。
- 在LeetCode上做题时遇到了一个很头痛的问题,就是如果输入的指数为-2^31时,我代码中将指数转换为正数时失败了。经过思考,我找到了原因,计算机在存储-2^31时是以补码的形式存储的,如果取其相反数,也就是将补码再次求补码,得到的还是补码本身,这就会让这个程序无法结束,解决方案是在函数中用long类型代替int来存储指数,以便求相反数。
代码
函数主体部分代码
package q16;
/**
* 数值的整数次方。
* 实现函数double Power(double base, int exponent),求base的exponent次方。
* 不得使用库函数,同时不需要考虑大数问题。
*/
public class Solution {
public double myPow(double x, int n) {
//任何数的0次方都是1。
//0的任何次方都没有数学意义。
if(((x-0.0 < 1e-9)&(x-0.0 > -1e-9) ) || n == 0)
{
return 1;
}
if ((x-1.0 < 1e-9)&(x-1.0 > -1e-9) || n == 1)
{
return x;
}
int flagOfNegative = 0;
//此处如果用int,在某些特殊情况会出错
long absN = n;
double result;
//当n<0时,先计算绝对值次方,再取倒数。
if (n < 0)
{
flagOfNegative = 1;
absN = -absN;
}
result = PowerOfPositive(x, absN);
if (flagOfNegative == 1)
{
result = 1.0/result;
}
return result;
}
public double PowerOfPositive(double x, long absN)
{
if(absN == 0)
{
return 1.0;
}
if (absN == 1)
{
return x;
}
//提高效率
double result = PowerOfPositive(x, absN>>1);
result = result * result;
//若absN为奇数,需要再乘一个x
if ((absN & 1) == 1)
{
result *= x;
}
return result;
}
}
测试部分代码
package q16;
public class TestApp {
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println("0的4次方是: " + solution.myPow(0, 4));
System.out.println("1的4次方是: " + solution.myPow(1, 4));
System.out.println("2的4次方是: " + solution.myPow(2, 4));
System.out.println("2的6次方是: " + solution.myPow(2, 6));
System.out.println("2的-2147483648次方是: " + solution.myPow(2, -2147483648));
}
}
运行结果截图
LeetCode运行截图