在数学中,计算 “a 的 b 次方” 叫做幂运算,比如计算 2 的 5 次方、10 的 3 次方。与 Python 直接提供 ** 运算符不同,在 C++ 中并没有专门的次方运算符,我们需要调用 <cmath> 头文件中的 std::pow() 函数来实现。
std::pow() 的基本用法
在使用 std::pow() 函数之前,我们需要先通过 #include <cmath> 引入头文件。其中,pow 是英文单词 “power(幂、次方)” 的缩写。
语法:
std::pow(base, exp)说明:
在 C++ 中,std::pow() 用于计算以 base 为底数、exp 为指数的次方结果,默认返回值类型为 double。它接收以下 2 个参数:
- base(必选):表示底数,支持传入整数或浮点数。
- exp(必选):表示指数(即次方数),同样支持传入整数或浮点数。
示例 1:计算整数与小数的次方
#include <cmath>
#include <iostream>
int main() {
double r1 = std::pow(2.0, 5.0); // 计算 2.0 的 5 次方
double r2 = std::pow(10, 3); // 计算 10 的 3 次方
double r3 = std::pow(1.5, 2); // 计算 1.5 的 2 次方
std::cout << r1 << '\n';
std::cout << r2 << '\n';
std::cout << r3 << '\n';
return 0;
}运行结果如下。
32
1000
2.25分析:
上面代码分别计算了 2.0 的 5 次方、10 的 3 次方以及 1.5 的 2 次方。可以看到,std::pow() 既可以接收 double 浮点数,也可以直接传入 int 整数。
需要注意的是,哪怕传入的两个参数都是 int 整数,std::pow() 内部也会先将它们转为 double 再计算。变量 r1 和 r2 保存的依然是 double 类型,屏幕上打印 32 和 1000 只是省略了末尾的 .0。
零次方、负指数与小数指数
除了常见的正整数次方之外,std::pow(base, exp) 的第 2 个参数 exp 还可以传入 0、负数或小数,分别对应数学中的以下 3 种规则:
- 指数为 0:任何非零数的 0 次方结果都等于 1,比如 5 的 0 次方等于 1。
- 指数为负数:表示正数次方的倒数,比如 2 的 -3 次方等于 1 除以 2 的 3 次方,即 1 除以 8 等于 0.125。
- 指数为小数:对应数学中的开方运算,比如 0.5 次方相当于求算术平方根,9 的 0.5 次方等于 3。
下面我们来看一个例子。
示例 2:特殊指数的幂运算
#include <cmath>
#include <iostream>
int main() {
std::cout << std::pow(5.0, 0.0) << '\n'; // 5.0 的 0 次方
std::cout << std::pow(2.0, -3.0) << '\n'; // 2.0 的 -3 次方
std::cout << std::pow(9.0, 0.5) << '\n'; // 9.0 的 0.5 次方
return 0;
}运行结果如下。
1
0.125
3分析:
std::pow(9.0, 0.5) 表示计算 9.0 的 0.5 次方,算出了 9 的算术平方根 3。不过在实际开发中,如果明确只是求算术平方根,我们更推荐直接调用 std::sqrt() 函数。这样不仅代码意图更直观,运算速度也更快。
此外小伙伴们要注意,当底数 base 为负数时,指数 exp 只能传入整数,比如 std::pow(-2, 3) 的结果为 -8。如果给负数底数搭配小数指数,写成 std::pow(-8.0, 1.0 / 3.0),函数会直接返回无效数字 NaN。
为什么不能使用 ^ 计算次方?
平时在键盘上输入数学算式时,很多人习惯把 “2 的 3 次方” 敲成 2^3。不少初学的小伙伴在写 C++ 代码时,也会顺着直觉写出 int res = 2 ^ 3;,结果发现程序虽然不报错,算出来的结果却完全不对。
这是因为在 C++ 中,^ 并不是次方运算符,而是位运算中的按位异或运算符。请看下面例子。
示例 3:对比 ^ 与 std::pow()
#include <cmath>
#include <iostream>
int main() {
int xorVal = 2 ^ 3; // 按位异或运算
double powVal = std::pow(2, 3); // 计算 2 的 3 次方
std::cout << xorVal << '\n';
std::cout << powVal << '\n';
return 0;
}运行结果如下。
1
8分析:
从运行结果可以看出,2 ^ 3 得到的结果是 1 而不是 8。按位异或会把十进制 2(二进制 010)和十进制 3(二进制 011)逐位对比,遵循 “相同为 0、不同为 1” 的规则:
010 ^ 011 -> 001二进制 001 换算成十进制就是 1。由于 2 ^ 3 在 C++ 语法中完全合法,编译器不会给出报错提醒,一旦写错排查起来很费时间。因此小伙伴们一定要记住:在 C++ 中计算次方统一调用 std::pow(),千万不要写成 ^。
整数平方与立方的写法选择
如果只是计算一个普通整数的平方或立方,比如已知正方形的整数边长 side 求面积,我们既可以调用 std::pow(side, 2),也可以直接写乘法 side * side。在实际开发中更推荐直接写乘法,主要有以下 2 个原因:
无需转换类型且速度更快:对于 int side = 6;,直接写 int area = side * side; 是一次纯粹的整数乘法,结果本身就是 int 类型。而调用 std::pow(side, 2) 会先把整数转为 double 计算,拿到结果后还需要再做一次类型转换。
避免浮点误差导致截断出错:std::pow() 内部采用浮点数运算。在部分平台下,计算较大整数次方可能产生极微小的浮点误差,比如本该是 100 却算出 99.99999999999999,直接强制转为 int 就会把小数抹掉变成 99。
因此,简单的整数平方、立方优先直接写 x * x 或 x * x * x。当指数较大需要调用 std::pow() 并将结果存入整型变量时,我们可以配合 std::round() 写成 (int)std::round(std::pow(2, 10)),先四舍五入再转换会准确得多。
