目录
正确代码
#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后,递归过程如下:
- 第一次调用pow(2, 5),exponent = 5 不等于0,且不是偶数,所以执行else语句
- 调用pow(2, 2)计算temp,因为2是偶数,所以再次调用pow(2, 1)
- 调用pow(2, 1)计算temp,此时exponent = 1 不等于0,且不是偶数,因此再次执行else语句
- 调用pow(2, 0)计算temp,由于exponent = 0,直接返回1。
- 回到第3步,将base乘以temp的平方,即2 * 1^2 = 2。
- 回到第2步,计算temp的平方,即2 * 2 = 4。
- 最终返回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++中,&运算符有以下几种用法:
- 取地址运算符:用于取得变量的地址,例如&a将返回变量a的地址。
- 按位与运算符:用于对两个数的每个二进制位进行逻辑与操作,例如a & b将返回a和b的按位与结果。
- 引用运算符:用于声明引用变量,例如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时,整个过程如下:
- 初始化result = 1.0,n = abs(5) = 5。
- 进入while循环,判断n是否为0。由于n不为0,继续执行。
- 判断n的二进制的最低位是否为1,即n & 1是否为1。由于5的二进制的最低位是1,所以条件满足,继续执行。
- result *= base,即result = 1.0 * 2 = 2.0。
- base *= base,即base = 2 * 2 = 4。
- n >>= 1,即将n右移一位,得到n = 2。
- 回到while循环,判断n是否为0。由于n不为0,继续执行。
- 判断n的二进制的最低位是否为1,即n & 1是否为1。由于2的二进制的最低位是0,所以条件不满足,跳过执行。
- base *= base,即base = 4 * 4 = 16。
- n >>= 1,即将n右移一位,得到n = 1。
- 回到while循环,判断n是否为0。由于n不为0,继续执行。
- 判断n的二进制的最低位是否为1,即n & 1是否为1。由于1的二进制的最低位是1,所以条件满足,继续执行。
- result *= base,即result = 2.0 * 16 = 32.0。
- base *= base,即base = 16 * 16 = 256。
- n >>= 1,即将n右移一位,得到n = 0。
- 回到while循环,判断n是否为0。由于n为0,跳出while循环。
- 返回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