实现函数
double power(double base, int exponent)
,求base
的exponent
次方。不得使用库函数,同时不需要考虑大数问题。
由于不需要考虑大数问题,所以很快就可以写出这样的代码
public static double power(double base, int exponent) {
double result = 1.0;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
但是这样的写法却不是完美的,如果指数是负数怎么办,从上面的程序看是不对的,另外如果 base
为 0
并且指数 exponent
为负数,此时 0
作为分母是没有意义的,所以进一步我们编写如下
public static double power(double base, int exponent) {
// 浮点数相等不能用 ==
if (Math.abs(base) < 0.0000000001 && exponent < 0) {
throw new RuntimeException("不能出现0的负次幂");
}
// 获得指数的绝对值
int absExponent = Math.abs(exponent);
// 使用计算指数为正数的方法计算值
double result = powerWithPositiveExponent(base, absExponent);
// 如果指数为负数,取倒数
if (exponent < 0) {
result = 1 / result;
}
return result;
}
// 该方法是用来求exponent为正数时的情况
private static double powerWithPositiveExponent(double base, int exponent) {
double result = 1.0;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
至此我们的代码已经比较好了,但是如果对效率进行极致的追求的话,我们还可以仔细的分析,对于 我们可以分解如下
%2F2%7D%20%5Ccdot%20a%5E%7B(n-1)%2F2%7D%20%5Ccdot%20a%20%26%20n%20%5C%25%202%20%3D%3D%201%0A%5Cend%7Bcases%7D%0A#card=math&code=a%5En%20%3D%20%0A%5Cbegin%7Bcases%7D%0Aa%5E%7Bn%2F2%7D%20%5Ccdot%20a%5E%7Bn%2F2%7D%20%26%20n%20%5C%25%202%20%3D%3D%200%20%5C%5C%0Aa%5E%7B%28n-1%29%2F2%7D%20%5Ccdot%20a%5E%7B%28n-1%29%2F2%7D%20%5Ccdot%20a%20%26%20n%20%5C%25%202%20%3D%3D%201%0A%5Cend%7Bcases%7D%0A)
比如我们求解 次方,按照上面的求解方法,我们要进行 次循环,但是通过上面的分析,我们知道 次方可以看做是两个 次方相乘,而 次方又可以看做是两个 次方的相乘,以此递推,只要 次即可得到结果,所以我们进一步修改 powerWithPositiveExponent
如下
private static double powerWithPositiveExponent(double base, int exponent) {
if (exponent == 0) {
return 1.0;
} else if (exponent == 1) {
return base;
}
double result = anotherPowerWithPositiveExponent(base, exponent >> 1);
result *= result;
// 使用位运算而不是求余 %
if ((exponent & 0x1) == 1) {
result *= base;
}
return result;
}
在上面我们使用了 exponent >> 1
,如果 exponent
为偶数,那么 exponent >> 1 = exponent / 2
,如果 exponent
为奇数,那么 exponent >> 1 = (exponent - 1) / 2
,所以我们不需要判断 exponent
是奇是偶,然后决定是除 还是减去 之后除 。