实现函数
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 是奇是偶,然后决定是除 还是减去
之后除
。
