快速幂(Java 实现代码)

本篇来说一下快速幂的原理,如果发现我叙述的听不明白,可以先去我之前的博客文章,有关数制了解一下

https://blog.csdn.net/assiduous_me/article/details/102295812

快速幂:快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高

原理:

对于 a^b 计算,一般做法是让 b 个 a 连续相乘

例如:3^10 一般做法,3^ 10 = 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3

但是这样的做法难免太慢了,为什么这么说呢?

我们可以这样做:3​​​​​​​^10 = 3^(1*2^3 + 0*2^2 + 1*2^1 + 0*2^0) = 3^(2^3) * 3^(2^2)

将次幂 10 变成二进制数字 1010,将次幂进行拆解,拆解为 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0

次幂加减对应的实际操作为对应数值相乘或相除操作

3^10 = (3^8) * (3^0) * (3^2) * (3^0) 

扫描二维码关注公众号,回复: 8519258 查看本文章

代码:

private static int pow(int n, int m) 
    int res = 1;                     
    int base = n;                    
    while(m != 0) {                  
        if ((m&1) == 1) {            
            res = res * base;        
        }                            
        base = base * base;          
        m = m >> 1;                  
    }                                
    return res;                      
}                                    

现在对代码进行解释:

n 表示底数,m 表示次幂
base = n 表示的是 n^(2^0)
m & 1 == 1 是判断 m 的二进制的最后一位是否为 1
m >> 1 是将 m 的二进制的最后一位移除,对于 1010 ,1010 >> 1 = 0101

下面带大家走一波手动 debug,pow(3, 10)
初始化:res = 3^0 = 1, base=3^(2^0)=3
m = 1010(2)

此时 m 不等于 0
判断 m & 1 ,因为 m 的末尾为 0,所以不等于 1
执行 base = base * base,此时 base =3^(2^0) * 3^(2^0) =  3^(2^1)
m >> 1 得 m = 101(2)


此时 m 不等于 0
判断 m & 1,因为 m 的末尾为1,所以执行
res = res * base,此时 res = 3^(2^1)
执行 base = base * base ,此时 base = 3^(2^1) * 3^(2^1) = 3^(2^2)
m >> 1 得 m = 10(2)

此时 m 不等于 0
判断 m & 1,因为 m 的末尾为 0,所以不等于 1
执行 base = base * base,此时 base = 3^(2^2) * 3^(2^2) = 3^(2^3)
m >> 1 得 m = 1(2)

此时 m 不等于 0
判断 m & 1,因为 m 的末尾为1,所以执行
res = res * base,此时 res = 3^(2^1) * 3^(2^3) = 3^10 
执行 base = base * base ,此时 base = 3^(2^3) * 3^(2^3) = 3^(2^4)
m >> 1 得 m = 0(2)

此时 m 等于 0
所以返回 res = 3^10,结束!!!
 

这下看懂了吧,神奇又巧妙,所以说学好数学很重要的,可惜我大学学高数的时候学的太差(;′⌒`),ok,如果大家有什么不明白的地方,可以在下面评论,我看到会回复你们的,(*^_^*)


 

发布了92 篇原创文章 · 获赞 23 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/assiduous_me/article/details/102303959