题目
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
解析
思路一
大多数一看这题感觉很简单,我当时也是,直接调用Math库即可呀,可是面试考的不是对API的熟练的程度,而是对数据逻辑处理能力,所以思路一调库这个可以直接pass掉了。
思路二
那就自己造轮子把,于是你可能迅速的写下了如下代码:
public static double Power2(double base, int exponent) {
double res = 1.0;
for(int i = 1; i <= exponent; i++) {
res *= base;
}
return res;
}
可是这样是不对的,因为未考虑如下几种情况:
1. 当exponent为负数时,上诉代码结果始终为1。
2. 当exponent为负数时,base是不能为0的。因为分母不能为0。
所以引出更加完备的思路三。
思路三
- 考虑到指数可能为负数
- 考虑到求负幂时,底数不能为0
- 考虑用logn的复杂度来求数的幂
- 递归形式
- 快速幂
递归形式
an={an/2an/2,a(n−1)/2a(n−1)/2a,n为偶数n为奇数
a
n
=
{
a
n
/
2
a
n
/
2
,
n为偶数
a
(
n
−
1
)
/
2
a
(
n
−
1
)
/
2
a
,
n为奇数
正常我们求24次方,需要24次乘法。但是当我们知道12次方的时候,可以直接对12次方乘以自身得到24,按照这样思路,24 -> 12 -> 6 -> 3 -> 1。只需5次乘法即可。
/**
* 递归的形式求快速幂
* @param base
* @param exponent
* @return
*/
public static double recursivePow(double base, int exponent) {
if(exponent == 0) {
return 1;
}
if(exponent == 1) {
return base;
}
double res = recursivePow(base, exponent >> 1);
//这里可以看递归公式,即可明白
if((exponent & 1) == 1) {
res *= base;
}
return res;
}
快速幂
看这篇博文
总的代码
/**
* 完备的double型的整数幂次方函数
* 这里用的快速幂思想
* @param base
* @param exponent
* @return
*/
public static double Power(double base, int exponent) {
if(equal(base, 0.0) && exponent < 0) {
throw new IllegalArgumentException("分母不能为0");
}
int absExponent = exponent < 0 ? -exponent : exponent;
double res = 1;
double t = base;
while(absExponent != 0) {
if((absExponent & 1) == 1) {
res *= t;
}
t *= t;
absExponent >>= 1;
}
return exponent < 0 ? 1.0 / res : res;
}
/**
* 判断double型数据的是否相等
* @param num1
* @param num2
* @return
*/
public static boolean equal(double num1, double num2) {
return num1 - num2 < 1e-8 && num1 - num2 > -1e-8;
}
总结
考察如下两方面:
1. 判断程序员是否思维缜密
2. 对快速求幂次方的掌握程度