【剑指offer】数值的整数次幂(快速幂)

题目描述:

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
解题方案:
第一种方案:最简单的方法就是使用Math类 .pow方法Math.pow()
   static double pow(double a, double b)
          Returns the value of the first argument raised to the power of the second argument.
第二种方案:快速幂

计算A^n的朴素的方法就是循环n次来求幂,这样便得到O(n)时间复杂度的方法,其实大家都想得到一种优化的方法即A^n=A^(n/2)*A^(n/2),一直递归下去,其间就可以省略很多不必要的计算,得到O(logn)的方法。

下面就介绍一种用二进制方法求快速幂的运算。

我们用二进制来代替幂n,比如10的二进制为1010(二进制相信大家都会)

这里第1位和第3位(倒着数)为1,于是我们求A^10便转化为A^10=A^(2^3)*A^(2^1);这样做有什么好处呢?

我们知道对于10(1010)来说每一个二进制位都对应着A的几次幂呢?分别是A^1   A^2   A^4   A^8(也是从低位开始的);注意到这里前后的幂的关系:A^(n) = A^(n-1)*A^(n-1)(这里的n表示二进制位的位数)不是么?比如A^8=A^4*A^4, A^4=A^2*A^2....

代码表示为:

while(n)  
{  
    if(n&1) //表示最后一位是1,因为我们可以通过移位来判断n的二进制位中哪些位为1  
    {  
      ans *= A;//ans表示最后的结果  
    }  
    A = A*A; //注意上面讲的前后二进制位对应的A的几次方的关系(移位的同时顺便计算出那一位代表的是A的几次方)  
    n>>1;  
}  
则本题的代码:

import java.util.Scanner;
/*
 * 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
 */
public class Power {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while(in.hasNext()){
			double base = in.nextDouble();
			int exponent1 = in.nextInt();
			
			double result = power(base, exponent1);
			System.out.println(result);
		}
	}

	public static double power(double base, int exponent1) {
		double res = 1,curr = base;
		int exponent;
		if(exponent1>0){
		    exponent = exponent1;
		}else if(exponent1<0){
		    if(base==0)
		        throw new RuntimeException("分母不能为0"); 
		    exponent = -exponent1;
		}else{// exponent1为0
		    return 1;// 任何数的0次方
		}
		while(exponent!=0){
		    if((exponent&1)==1)
		        res*=curr;
		    curr*=curr;// 翻倍
		    exponent>>=1;//右移一位
		 }
		return exponent1>=0?res:(1/res);
	}
}




猜你喜欢

转载自blog.csdn.net/smile_yangyue/article/details/79167092