快速幂——基于java实现

本文介绍了使用pow函数和自定义for循环计算幂的O(n)时间复杂度方法,然后重点讲解了快速幂算法的分治思想,以及从二进制角度的解释,包括如何通过位运算和循环迭代实现高效计算,给出了Java代码实现。
摘要由CSDN通过智能技术生成

一、算法简介

1.使用pow函数和自定义的for循环的时间复杂度为O(n)

/**计算x的y次方**/
//1.使用Pow函数
double res = Math.pow(x,y);
//2.自定义for循环
double res=x;
for(int i=1;i<y;i++){
     res=res*x;
}

2.快速幂的时间复杂度为O(log n)

二、快速幂的思想

(1)从分冶的角度出发,计算   x^{y}

           ①假设y为偶数,即计算  3^{8}

                3^{8}=3^{2*4}=9^{4}=9^{2*2}=81^{2}=6561^{1}

                我们将指数 y,每次划分为 \frac{y}{2} ,上述式子不需要进行8次循环,而只需要三步即可完                成,注 3^{2*4} 和9^{2*2} 是为了让读者好理解,而重复写的。

            ②假设y为奇数,即计算 3^{11}

                3^{11}=3^{1+10}=3*3^{10}=3*9^{5}=3*9^{1+4}=3*9*81^{2}    =3*9*6561^{1}

                指数部分为奇数是可以化解成(1+偶数)的形式的,这样我们可以把指数为1的底                 拿出来当答案来乘,偶数部分同①继续化解即可

伪代码
    x=3,y=10,res=1
   while(指数y不等于0){
    if(指数y为奇数){
        res = res * x //提取底数出来,作为乘积
    }
    y=y/2 //指数二分
    x=x*x //底数平方

}

(2) 从二进制的角度出发

        如8的二进制位:8=1000_{2}

        二进制转十进制:1000_{2}=1*2^3+0*2^2+0*2^1+0*2^0=8

        那么3^8=3^{(1000)_{2}}=3^{1*2^3+0*2^2+0*2^1+0*2^0}=3^{0*2^0}*3^{0*2^1}*3^{0*2^2}*3^{1*2^3}     (倒序写)

        观察发现:指数部分是由两部分组成,第一部分是0001,第二部分是      2^0,2^1,2^2,2^3,发现2是循环增大的(用代码x=x*x,循环迭代出来,但是否使用则看二进制位是否为‘1’),由于二进制要么为0要么为1(用代码 y&1==1,来判断)

        再举个详细的例子(计算3^{11}):

        11=1011

        3^{11}=3^{1*2^{0}}*3^{1*2^{1}}*3^{0*2^{2}}*3^{1*2^{3}}=3^{1*1}*3^{1*2}*3^{0*4}*3^{1*8}
      

伪代码:

 x=3,y=11,res=1

 while( (1011)y从尾往头读取){

  if( (y&1)==1){

     res=res*x;  //二进制位不为0,则相乘

     //如第一个1:res=1*3,    

     //第二个1:res=res*3^2

     //第三个数为0:不相乘,但x是不断平方的,此时是x^4

     //第四个数为1:res=res*3^8  ,注意哦,平方是在if后面

       }

    二进制右移一位

    x=x*x; //依次迭代3^0,3^1,3^2,3^4,3^8................

 }

 三、代码实现

   public static double FastPow(int x,int y){
        double res= 1;
        while (y!=0){ 
            if(y%2 == 1){ //指数为奇数,也可以利用位运算:(y&1)==1 (与操作): 判断 n 二进制最右一位是否为 1
                res *= x;
            }
            y=y/2;  //指数循环二分,y>>=1 (移位操作): n 右移一位(可理解为删除最后一位,即除以2)。
            x=x*x;  //底数平分

        }
        return res;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值