实现函数 double power(double base, int exponent),求 baseexponent 次方。不得使用库函数,同时不需要考虑大数问题。

    由于不需要考虑大数问题,所以很快就可以写出这样的代码

    1. public static double power(double base, int exponent) {
    2. double result = 1.0;
    3. for (int i = 0; i < exponent; i++) {
    4. result *= base;
    5. }
    6. return result;
    7. }

    但是这样的写法却不是完美的,如果指数是负数怎么办,从上面的程序看是不对的,另外如果 base0 并且指数 exponent 为负数,此时 0 作为分母是没有意义的,所以进一步我们编写如下

    1. public static double power(double base, int exponent) {
    2. // 浮点数相等不能用 ==
    3. if (Math.abs(base) < 0.0000000001 && exponent < 0) {
    4. throw new RuntimeException("不能出现0的负次幂");
    5. }
    6. // 获得指数的绝对值
    7. int absExponent = Math.abs(exponent);
    8. // 使用计算指数为正数的方法计算值
    9. double result = powerWithPositiveExponent(base, absExponent);
    10. // 如果指数为负数,取倒数
    11. if (exponent < 0) {
    12. result = 1 / result;
    13. }
    14. return result;
    15. }
    16. // 该方法是用来求exponent为正数时的情况
    17. private static double powerWithPositiveExponent(double base, int exponent) {
    18. double result = 1.0;
    19. for (int i = 0; i < exponent; i++) {
    20. result *= base;
    21. }
    22. return result;
    23. }

    至此我们的代码已经比较好了,但是如果对效率进行极致的追求的话,我们还可以仔细的分析,对于 数值的整数次方 - 图1 我们可以分解如下

    数值的整数次方 - 图2%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)

    比如我们求解 数值的整数次方 - 图3 次方,按照上面的求解方法,我们要进行 数值的整数次方 - 图4 次循环,但是通过上面的分析,我们知道 数值的整数次方 - 图5 次方可以看做是两个 数值的整数次方 - 图6 次方相乘,而 数值的整数次方 - 图7 次方又可以看做是两个 数值的整数次方 - 图8 次方的相乘,以此递推,只要 数值的整数次方 - 图9 次即可得到结果,所以我们进一步修改 powerWithPositiveExponent 如下

    1. private static double powerWithPositiveExponent(double base, int exponent) {
    2. if (exponent == 0) {
    3. return 1.0;
    4. } else if (exponent == 1) {
    5. return base;
    6. }
    7. double result = anotherPowerWithPositiveExponent(base, exponent >> 1);
    8. result *= result;
    9. // 使用位运算而不是求余 %
    10. if ((exponent & 0x1) == 1) {
    11. result *= base;
    12. }
    13. return result;
    14. }

    在上面我们使用了 exponent >> 1,如果 exponent 为偶数,那么 exponent >> 1 = exponent / 2,如果 exponent 为奇数,那么 exponent >> 1 = (exponent - 1) / 2,所以我们不需要判断 exponent 是奇是偶,然后决定是除 数值的整数次方 - 图10 还是减去 数值的整数次方 - 图11 之后除 数值的整数次方 - 图12