声明:若无特殊说明,本文的 $a^b$ 表示 $a$ 的 $b$ 次方


幂函数的朴素实现

如果我们想要实现幂函数 pow(x,n) 最自然的想法就是设置一个循环,记录 x 累乘 n 次的结果。这种思路的代码实现过于简单,所以不予展示。

但是这样,我们的时间复杂度是 O(n)n 比较大的时候,我们也需要承担比较大的代价。

有没有更快的算法呢?

乘法快速幂

我们可以这样计算 $3^7$,因为 $3^7=3^4 \times 3^3$,$3^3=3^2 \times 3^1$,$3^2=3^1 \times 3^1$。

所以 $3^7=3^4 \times 3^2 \times 3^1$。

我们每次都只需要折半计算幂,然后通过幂运算的性质来得到结果,比如 $3^7=3^4 \times 3^3$,就不需要经过计算 $3^6$ 的环节。

每次都折半进行计算,这不就是对 $y$ 进行二进制分解的过程吗?

简单地说,$(7)_{10}=(1011)_2$,也就是说,$7=2^2+2^1+2^0$。

根据幂运算的性质就可以得到:

$$x^7=x^{(2^2+2^1+2^0)}=x^{(2^2)} \times x^{(2^1)} \times x^{(2^0)}$$

所以我们只需要计算 $x^1$、$x^2$、$x^4$。

这很简单,$x$ 的初始值就是 $x^1$。

要想实现 $x^2$,我们让 $x$ 再乘上自身即可,$x^4$ 同理。

这样,我们的代码实现就比较简单了。

我们先对 $y$ 进行二进制分解,分解完,我们只看有 1 的部分。

还是拿 7 举例子,二进制下的 7 是 $1011$。

  • 看第 0 位,是 1,所以答案需要乘上 $x^{(2^0)}$
  • 看第 1 位,是 1,所以答案需要乘上 $x^{(2^1)}$
  • 看第 2 位,是 0,所以答案不需要更改
  • 看第 3 位,是 1,所以答案需要乘上 $x^{(2^3)}$

下面是代码实现,C++ 由于没有使用到其常用特性,所以参考 C 语言版本。


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
// 这里用int只是为了演示算法,具体数据类型依据具体数据量 
int myPower(int x, int y){
    int ret = 1;
    while(y != 0){
        if((y & 1) != 0){
            ret *= x;
        }
        x *= x;
        y >>= 1;
    }
    return ret;
}
int main(){
    srand(time(NULL));
    for(int x = 1; x <= 10; ++x){
        int y = rand() % 6 + 2;
        printf("%d的%d次方是%d,标准库函数核对结果:%d\n", 
                x, y, myPower(x, y), (int)pow(x, y));
    }
    return 0;
}
import random
import math

def myPower(x, y):
    ret = 1
    while y != 0:
        if (y & 1) != 0:
            ret *= x
        x *= x
        y >>= 1
    return ret

for x in range(1, 11):
    y = random.randint(2, 7)
    print(f"{x}{y}次方是{myPower(x, y)},标准库函数核对结果:{int(math.pow(x, y))}")

本站总访问量 0 次,今日访问量 0 次。
觉得好的可以帮忙扩散哦 Ciallo~(∠・ω< )⌒☆