PTAL1-012 计算指数 + pow函数代码实现详讲

目录

 正确代码

pow函数代码简单实现

递归实现(递归幂运算)

递归的老毛病了

迭代(快速幂运算)

预备知识:

&运算符

>>=操作符

举例

过程(建议看)


 正确代码

#include<iostream>
#include<cmath>
using namespace std;

int main(){
    int n;
    cin>>n;
    int result=pow(2,n);
    cout<<"2^"<<n<<" = "<<result;
    return 0;
}

pow函数代码简单实现

递归实现(递归幂运算)

double pow(double base, int exponent) {
    if (exponent == 0) {
        return 1;
    }
    if (exponent % 2 == 0) {
        double temp = pow(base, exponent / 2);
        return temp * temp;
    } else {
        double temp = pow(base, (exponent - 1) / 2);
        return base * temp * temp;
    }
}

传入2,5后,递归过程如下:

  1. 第一次调用pow(2, 5),exponent = 5 不等于0,且不是偶数,所以执行else语句
  2. 调用pow(2, 2)计算temp,因为2是偶数,所以再次调用pow(2, 1)
  3. 调用pow(2, 1)计算temp,此时exponent = 1 不等于0,且不是偶数,因此再次执行else语句
  4. 调用pow(2, 0)计算temp,由于exponent = 0,直接返回1。
  5. 回到第3步,将base乘以temp的平方,即2 * 1^2 = 2。
  6. 回到第2步,计算temp的平方,即2 * 2 = 4。
  7. 最终返回2 * 4 * 4 = 32。

因此,pow(2, 5)的结果为32。

这个实现首先检查指数是否为零,如果是则返回1。接着,它通过检查指数是否为偶数来确定是否需要递归调用自身两次。如果是,则将指数除以2进行递归计算,最后将结果平方。如果指数为奇数,则将指数减去1,并将新的指数除以2进行递归计算,然后将结果与基数相乘,再将结果平方。

注意:以上实现并不完善,还有一些特殊情况没有考虑到,例如负数幂和浮点数幂等情况。在实际开发中应该考虑到这些情况。

递归的老毛病了

时间复杂度和空间复杂度。

迭代(快速幂运算)

double power(double base, int exponent) {
    double result = 1.0;
    int n = abs(exponent);
    while (n != 0) {
        if (n & 1) {    // 判断n的二进制是否存在当前位上
            result *= base;
        }
        base *= base;
        n >>= 1;        // n右移一位
    }
    return exponent >= 0 ? result : 1 / result;
}

预备知识:

&运算符

在C++中,&运算符有以下几种用法:

  1. 取地址运算符:用于取得变量的地址,例如&a将返回变量a的地址。
  2. 按位与运算符:用于对两个数的每个二进制位进行逻辑与操作,例如a & b将返回a和b的按位与结果。
  3. 引用运算符:用于声明引用变量,例如int &a = b将声明一个名为a的引用变量,它是变量b的别名。

这里要用到第二个,按位与运算法。

例如:

例子1:表达式n&2表示将n和2的二进制位逐位进行与(AND)操作,返回一个新的二进制数,其中只有n和2都为1的位才为1,其余为0。如果n的第二个位是1,则n&2将返回2,否则返回0。

例子2:n=5     代码中的n&1的意思是,   将5的二进制表示的数(00000101)与(00000001)进行(AND)操作,返回一个新的二进制数,由于同一位上只有都为1时,才为1,否则为0

所以无论除了5的最低位的其他的位数如何,只有最低位不为1,那它就是0

其实说白了就是与运算。

>>=操作符

>>="操作符通常用于将变量的值向右移动指定数量的二进制位,并将结果赋给该变量。

比如  a=3   a>>=1

实际上就是   00000011       向右移一位成为    00000001     再赋值给a      最后a就等于1了。

移动后最高位不是空了吗,没关系,系统会补0

举例

这段代码实现了一个求幂函数,采用的是快速幂算法。当传入参数base为2,exponent为5时,整个过程如下:

  1. 初始化result = 1.0,n = abs(5) = 5。
  2. 进入while循环,判断n是否为0。由于n不为0,继续执行。
  3. 判断n的二进制的最低位是否为1,即n & 1是否为1。由于5的二进制的最低位是1,所以条件满足,继续执行。
  4. result *= base,即result = 1.0 * 2 = 2.0。
  5. base *= base,即base = 2 * 2 = 4。
  6. n >>= 1,即将n右移一位,得到n = 2。
  7. 回到while循环,判断n是否为0。由于n不为0,继续执行。
  8. 判断n的二进制的最低位是否为1,即n & 1是否为1。由于2的二进制的最低位是0,所以条件不满足,跳过执行。
  9. base *= base,即base = 4 * 4 = 16。
  10. n >>= 1,即将n右移一位,得到n = 1。
  11. 回到while循环,判断n是否为0。由于n不为0,继续执行。
  12. 判断n的二进制的最低位是否为1,即n & 1是否为1。由于1的二进制的最低位是1,所以条件满足,继续执行。
  13. result *= base,即result = 2.0 * 16 = 32.0。
  14. base *= base,即base = 16 * 16 = 256。
  15. n >>= 1,即将n右移一位,得到n = 0。
  16. 回到while循环,判断n是否为0。由于n为0,跳出while循环。
  17. 返回exponent >= 0 ? result : 1 / result,即返回result的值,结果为32.0。

过程(建议看)

base:         2                       4                    16                        256

n:               00000101         00000010      00000001      00000000      

进if否:        进                     不进                进              循环先结束了

result*=base:

                     1*2                                       2*16          

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天写bug的屑闲鱼

请我杯饮料吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值