在 C++ 中,如果想要求一个非负数的算术平方根,比如已知正方形面积求边长,我们可以直接调用 <cmath> 头文件中的 std::sqrt() 函数。
除了求算术平方根之外,<cmath> 头文件还提供了另外两个实用的配套函数:用于根据两条直角边求斜边的 std::hypot(),以及用于求立方根的 std::cbrt()。
std::sqrt() 的基本用法
在使用 std::sqrt() 函数之前,我们需要先在代码顶部通过 #include <cmath> 引入头文件。其中,sqrt 是英文 “square root(平方根)” 的缩写。
语法:
std::sqrt(x)说明:
参数 x 表示被开方数,支持传入整数或浮点数,在实数范围内要求 x >= 0。很多正数开平方的结果都是带小数的无理数,比如 2 的平方根约为 1.41421。因此哪怕传入的是 int 整数,std::sqrt() 也会自动将其转为 double 并返回 double 类型的结果。
示例 1:计算正数与小数的平方根
#include <cmath>
#include <iostream>
int main() {
double r1 = std::sqrt(81.0); // 完全平方数
double r2 = std::sqrt(2); // 普通正整数
double r3 = std::sqrt(2.25); // 小数
std::cout << r1 << '\n';
std::cout << r2 << '\n';
std::cout << r3 << '\n';
return 0;
}运行结果如下。
9
1.41421
1.5分析:
因为 9 乘以 9 等于 81、1.5 乘以 1.5 等于 2.25,所以 std::sqrt(81.0) 和 std::sqrt(2.25) 分别返回了 9 和 1.5。而整数 2 开平方除不尽,std::cout 默认输出了保留 6 位有效数字的近似值 1.41421。
需要注意的是,在实数范围内任何数的平方都是非负数,负数没有实数平方根。如果写出 std::sqrt(-9.0) 传入负数,函数就会返回特殊浮点值 NaN,表示不是一个有效数字。
因此当被开方数来自外部输入时,小伙伴们记得先判断并确保 x >= 0,然后再调用 std::sqrt(x)。
计算直角三角形斜边:std::hypot()
求平方根最经典的一个应用,就是根据勾股定理把两条直角边的平方相加后再开平方,用来求直角三角形的斜边长度或平面上两点间的直线距离。
在 C++ 中,除了手动写出 std::sqrt(x * x + y * y) 之外,我们还可以直接调用 <cmath> 头文件提供的 std::hypot() 函数。其中,hypot 是英文单词 “hypotenuse(直角三角形斜边)” 的缩写。
语法:
std::hypot(x, y)说明:
参数 x 和 y 表示两条直角边的长度,支持传入整数或浮点数,返回值为 double 类型。调用后,std::hypot(x, y) 会自动算出 x 的平方加 y 的平方之后的算术平方根。
此外,当 x 或 y 的数值非常大时,如果自己先算 x * x 很容易超出 double 的最大表示范围而变成无穷大 inf。std::hypot() 则在内部做了专门的防溢出处理,计算起来更加安全。
示例 2:计算直角三角形斜边
#include <cmath>
#include <iostream>
int main() {
double a = 3.0;
double b = 4.0;
double c = std::hypot(a, b); // 根据两条直角边求斜边
std::cout << c << '\n';
return 0;
}运行结果如下。
5分析:
std::hypot(a, b) 表示根据两条直角边 3.0 和 4.0 直接计算斜边长度,算出的结果为 5,正好对应我们熟悉的 “勾三股四弦五”。
对于这个例子来说,下面 2 种方式是等价的。
// 方式 1(推荐)
double c = std::hypot(a, b);
// 方式 2
double c = std::sqrt(a * a + b * b);其中,方式 1 省去了手动把每个变量自乘一遍的麻烦。比如已知平面上两点的坐标,当我们算出横向差值 dx = x2 - x1 和纵向差值 dy = y2 - y1 后,直接写 std::hypot(dx, dy) 就能一步算出两点间的直线距离。
求立方根:std::cbrt()
如果我们需要求一个数的立方根(即开三次方),可以调用 <cmath> 头文件中的 std::cbrt() 函数。其中,cbrt 是英文 “cube root(立方根)” 的缩写。
语法:
std::cbrt(x)说明:
参数 x 表示被开方数,支持传入正数、0 或负数,整数与浮点数均可,返回值为 double 类型。
示例 3:计算正负数的立方根
#include <cmath>
#include <iostream>
int main() {
std::cout << std::cbrt(27.0) << '\n'; // 正数的立方根
std::cout << std::cbrt(-27.0) << '\n'; // 负数的立方根
std::cout << std::cbrt(8) << '\n'; // 整数的立方根
return 0;
}运行结果如下。
3
-3
2分析:
在这个例子中,因为 3 的立方等于 27、-3 的立方等于 -27,所以 std::cbrt(27.0) 和 std::cbrt(-27.0) 分别返回了 3 和 -3。
这里小伙伴们要注意区分平方根与立方根对负数的不同规则:平方根 std::sqrt(x) 不能传入负数,否则会产生 NaN。而负数的立方依然是负数,因此立方根 std::cbrt(x) 可以正常接收负数并算出准确结果。
注意 求立方根且被开方数可能为负数时,我们应该使用专用的 std::cbrt(x),不要改用 std::pow() 写成 std::pow(x, 1.0 / 3.0)。因为 std::pow() 在底数为负数且指数为小数时会返回 NaN,无法算出负数的立方根。
