快速幂非递归实现(即求x的n次方)

如果用递归的方法求幂, 代码可以是这样的:

double Pow(double x, unsigned int n)
{
    if (n == 0)
        return 1;
    if (n == 1)
        return x;
    if (n & 1 == true)      // 如果n是奇数
        return Pow(x * x, n / 2) * x;
    else                    // 如果n是偶数
        return Pow(x * x, n / 2);
}

注意:

  1. n若为一个奇数,那么它对应的二进制最后一位一定是1,与上1最终一定是1
  2. 上面的n为非负,如果要求负数次幂,可以先求正数次幂再用1除之

上述方法虽然简单, 但是效率并不高. 因为函数调用的代价非常昂贵. 用循环实现的效率更高.

用循环做的话,当然不能直接死乘。举个例子:
在这里插入图片描述
直接乘要做998次乘法,效率很低。但事实上可以这样做,先求出2^k次幂:

在这里插入图片描述
再相乘:
在这里插入图片描述
这样只要做16次乘法。即使加上一些辅助的存储和运算,也比直接乘高效得多(尤其如果这里底数是成百上千位的大数字的话)。
我们发现,把999转为2进制数:1111100111,其各位就是要乘的数。

再举一个例子帮助理解,其中次角标2代表二进制。

因此就可以写出下面的非递归版代码:

double Pow(double x, int n)
{
    double result = 1;
    while (n)
    {
        if (n & 1)        //  等价于判断n的末位是不是1
            result *= x;
        n >>= 1;          // 将n右移一位,即遍历原n的二进制的每一位
        x *= x;  // n右移了一位,x补上
    }
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值