#include <cmath>
用法总结
#include <cmath>
是 C++ 标准库中的头文件,提供了一系列用于执行常见数学运算的函数。与 C 语言中的<math.h>
类似,但它将函数声明放在std
命名空间中,以更好地与 C++ 的命名空间特性相兼容。使用cmath
可以在 C++ 程序中进行各种数学计算,包括基本的算术运算、三角函数、指数和对数运算、取整函数等。
是否为标准库
#include <cmath>
是 C++ 标准库的一部分,提供了数学计算所需的函数和常量,使用该头文件可以使 C++ 程序更方便地进行数学操作,无需额外的外部库。
cmath
头文件中的所有函数
- 基本数学运算函数:
std::abs(double x)
:计算浮点数x
的绝对值。std::pow(double x, double y)
:计算x
的y
次幂。std::sqrt(double x)
:计算x
的平方根。std::cbrt(double x)
:计算x
的立方根。std::hypot(double x, double y)
:计算直角三角形斜边长度,即sqrt(x*x + y*y)
。
- 三角函数:
std::sin(double x)
、std::cos(double x)
、std::tan(double x)
:分别计算x
的正弦、余弦和正切值。std::asin(double x)
、std::acos(double x)
、std::atan(double x)
:分别计算x
的反正弦、反余弦和反正切值。std::atan2(double y, double x)
:计算y/x
的反正切值,考虑了x
和y
的符号。
- 指数和对数函数:
std::exp(double x)
:计算自然常数e
的x
次幂。std::log(double x)
:计算x
的自然对数(以e
为底)。std::log10(double x)
:计算x
的以 10 为底的对数。std::log2(double x)
:计算x
的以 2 为底的对数。
- 舍入和取整函数:
std::floor(double x)
:将x
向下舍入到最接近的整数。std::ceil(double x)
:将x
向上舍入到最接近的整数。std::round(double x)
:将x
四舍五入到最接近的整数。std::trunc(double x)
:截断x
的小数部分,只保留整数部分。
- 其他函数:
std::fmod(double x, double y)
:计算x
除以y
的余数。std::fmax(double x, double y)
:返回x
和y
中的最大值。std::fmin(double x, double y)
:返回x
和y
中的最小值。std::remainder(double x, double y)
:计算x
除以y
的 IEEE 754 余数。
cmath
头文件中的函数及代码实例
- 基本数学运算函数:
std::abs(double x)
:计算浮点数x
的绝对值。
#include <iostream> #include <cmath> int main() { double num = -5.5; std::cout << "The absolute value of " << num << " is " << std::abs(num) << std::endl; return 0; }
std::pow(double x, double y)
:计算x
的y
次幂。
#include <iostream> #include <cmath> int main() { double base = 2.0; double exponent = 3.0; std::cout << base << " raised to the power of " << exponent << " is " << std::pow(base, exponent) << std::endl; return 0; }
std::sqrt(double x)
:计算x
的平方根。
#include <iostream> #include <cmath> int main() { double num = 25.0; std::cout << "The square root of " << num << " is " << std::sqrt(num) << std::endl; return 0; }
std::cbrt(double x)
:计算x
的立方根。
#include <iostream> #include <cmath> int main() { double num = 27.0; std::cout << "The cube root of " << num << " is " << std::cbrt(num) << std::endl; return 0; }
std::hypot(double x, double y)
:计算直角三角形斜边长度,即sqrt(x*x + y*y)
。
#include <iostream> #include <cmath> int main() { double x = 3.0; double y = 4.0; std::cout << "The hypotenuse of a right triangle with sides " << x << " and " << y << " is " << std::hypot(x, y) << std::endl; return 0; }
- 三角函数:
std::sin(double x)
、std::cos(double x)
、std::tan(double x)
:分别计算x
的正弦、余弦和正切值。
#include <iostream> #include <cmath> int main() { double angle = 0.5; // 弧度 std::cout << "sin(" << angle << ") = " << std::sin(angle) << std::endl; std::cout << "cos(" << angle << ") = " << std::cos(angle) << std::endl; std::cout << "tan(" << angle << ") = " << std::tan(angle) << std::endl; return 0; }
std::asin(double x)
、std::acos(double x)
、std::atan(double x)
:分别计算x
的反正弦、反余弦和反正切值。
#include <iostream> #include <cmath> int main() { double value = 0.5; std::cout << "asin(" << value << ") = " << std::asin(value) << std::endl; std::cout << "acos(" << value << ") = " << std::acos(value) << std::endl; std::cout << "atan(" << value << ") = " << std::atan(value) << std::endl; return 0; }
std::atan2(double y, double x)
:计算y/x
的反正切值,考虑了x
和y
的符号。
#include <iostream> #include <cmath> int main() { double y = 1.0; double x = 1.0; std::cout << "atan2(" << y << ", " << x << ") = " << std::atan2(y, x) << std::endl; return 0; }
- 指数和对数函数:
std::exp(double x)
:计算自然常数e
的x
次幂。
#include <iostream> #include <cmath> int main() { double exponent = 1.0; std::cout << "e raised to the power of " << exponent << " is " << std::exp(exponent) << std::endl; return 0; }
std::log(double x)
:计算x
的自然对数(以e
为底)。
#include <iostream> #include <cmath> int main() { double num = std::exp(1.0); std::cout << "The natural logarithm of " << num << " is " << std::log(num) << std::endl; return 0; }
std::log10(double x)
:计算x
的以 10 为底的对数。
#include <iostream> #include <cmath> int main() { double num = 100.0; std::cout << "The base-10 logarithm of " << num << " is " << std::log10(num) << std::endl; return 0; }
std::log2(double x)
:计算x
的以 2 为底的对数。
#include <iostream> #include <cmath> int main() { double num = 8.0; std::cout << "The base-2 logarithm of " << num << " is " << std::log2(num) << std::endl; return 0; }
- 舍入和取整函数:
std::floor(double x)
:将x
向下舍入到最接近的整数。
#include <iostream> #include <cmath> int main() { double num = 3.7; std::cout << "Floor of " << num << " is " << std::floor(num) << std::endl; return 0; }
std::ceil(double x)
:将x
向上舍入到最接近的整数。
向上取整是一种数学运算,对于一个浮点数x
,向上取整的结果是大于或等于x
的最小整数。例如:
- 如果
x = 3.14
,那么ceilf(x)
的结果是4
。 - 如果
x = 5.0
,那么ceilf(x)
的结果是5
。 - 如果
x = -2.3
,那么ceilf(x)
的结果是-2
。
在 C++ 中,ceilf
函数的原型是 float ceilf(float x);
,它接受一个单精度浮点数 x
作为输入,并返回一个单精度浮点数,该浮点数是大于或等于 x
的最小整数。
以下是一个代码示例,展示了 ceilf
函数的使用:
#include <iostream>
#include <cmath>
int main() {
float num1 = 3.14f;
float num2 = 5.0f;
float num3 = -2.3f;
std::cout << "ceilf(" << num1 << ") = " << ceilf(num1) << std::endl;
std::cout << "ceilf(" << num2 << ") = " << ceilf(num2) << std::endl;
std::cout << "ceilf(" << num3 << ") = " << ceilf(num3) << std::endl;
return 0;
}
在这个示例中,我们使用 ceilf
函数对三个不同的浮点数进行向上取整操作,并将结果输出到控制台。
ceilf
函数在许多场景中都很有用,例如:
- 在计算需要将空间划分为离散块时,如上述将空间划分为体素块的代码中,使用
ceilf
确保能够完全覆盖空间,避免因向下取整而导致部分空间未被划分。 - 在资源分配问题中,如果要分配一定数量的资源给多个任务,并且每个任务需要至少一个资源,使用向上取整可以确保有足够的资源分配,即使计算结果是小数。
此外,C++ 中还有 ceil
函数,它接受 double
类型的参数,返回 double
类型的结果,使用方式与 ceilf
类似,例如:
#include <iostream>
#include <cmath>
int main() {
double num = 3.14;
std::cout << "ceil(" << num << ") = " << ceil(num) << std::endl;
return 0;
}
如果你使用 ceil
函数,需要包含 cmath
头文件,它遵循相同的向上取整规则,但处理双精度浮点数。对于整数部分是负数的浮点数,向上取整会向 0 的方向取整,即取绝对值较小的整数,例如 ceil(-2.3)
是 -2
而不是 -3
。
总之,向上取整是一种确保得到的结果是大于或等于原始值的最小整数的操作,在需要将连续的浮点数转换为离散的整数,并且需要覆盖整个范围时非常有用。
std::round(double x)
:将x
四舍五入到最接近的整数。
#include <iostream>
#include <cmath>
int main() {
double num = 3.5;
std::cout << "Round of " << num << " is " << std::round(num) << std::endl;
return 0;
}
std::trunc(double x)
:截断x
的小数部分,只保留整数部分。#include <iostream> #include <cmath> int main() { double num = 3.8; std::cout << "Trunc of " << num << " is " << std::trunc(num) << std::endl; return 0; }
- 其他函数:
std::fmod(double x, double y)
:计算x
除以y
的余数。
#include <iostream> #include <cmath> int main() { double dividend = 10.0; double divisor = 3.0; std::cout << dividend << " modulo " << divisor << " is " << std::fmod(dividend, divisor) << std::endl; return 0; }
std::fmax(double x, double y)
:返回x
和y
中的最大值。
#include <iostream> #include <cmath> int main() { double num1 = 5.0; double num2 = 10.0; std::cout << "The maximum of " << num1 << " and " << num2 << " is " << std::fmax(num1, num2) << std::endl; return 0; }
std::fmin(double x, double y)
:返回x
和y
中的最小值。
#include <iostream> #include <cmath> int main() { double num1 = 5.0; double num2 = 10.0; std::cout << "The minimum of " << num1 << " and " << num2 << " is " << std::fmin(num1, num2) << std::endl; return 0; }
std::remainder(double x, double y)
:计算x
除以y
的 IEEE 754 余数。
#include <iostream> #include <cmath> int main() { double dividend = 10.0; double divisor = 3.0; std::cout << dividend << " remainder by " << divisor << " is " << std::remainder(dividend, divisor) << std::endl; return 0; }
机器人 SLAM 方向上的项目实例代码
以下是一个更完整的机器人 SLAM 项目中的代码示例,使用了 cmath
中的多个函数:
#include <iostream>
#include <vector>
#include <cmath>
#include <cmath>
#include <random>
struct Pose {
double x;
double y;
double theta;
};
class RobotSLAM {
public:
RobotSLAM() : robot_pose{0.0, 0.0, 0.0} {}
// 模拟机器人运动
void move(double linear_velocity, double angular_velocity, double time) {
double delta_theta = angular_velocity * time;
double distance = linear_velocity * time;
robot_pose.theta += delta_theta;
robot_pose.x += distance * std::cos(robot_pose.theta);
robot_pose.y += distance * std::sin(robot_pose.theta);
}
// 模拟激光雷达测量
std::vector<double> sense() {
std::vector<double> measurements;
std::default_random_engine gen;
std::normal_distribution<double> dist(5.0, 0.5); // 均值为 5,标准差为 0.5 的正态分布
for (int i = 0; i < 10; ++i) {
double measurement = dist(gen);
measurements.push_back(measurement);
}
return measurements;
}
// 根据测量更新地图
void updateMap(const std::vector<double>& measurements, double sensor_angle_increment) {
double angle = robot_pose.theta - M_PI / 2;
for (const auto& measurement : measurements) {
double global_x = robot_pose.x + measurement * std::cos(angle);
double global_y = robot_pose.y + measurement * std::sin(angle);
map.push_back({global_x, global_y});
angle += sensor_angle_increment;
}
}
// 打印地图
void printMap() const {
for (const auto& point : map) {
std::cout << "Point: (" << point.x << ", " << point.y << ")" << std::endl;
}
}
private:
Pose robot_pose;
std::vector<Pose> map;
};
int main() {
RobotSLAM slam;
double linear_velocity = 0.5; // 线速度
double angular_velocity = 0.1; // 角速度
double time_step = 1.0; // 时间步长
double sensor_angle_increment = M_PI / 5; // 激光雷达角度增量
for (int i = 0; i < 5; ++i) {
slam.move(linear_velocity, angular_velocity, time_step);
auto measurements = slam.sense();
slam.updateMap(measurements, sensor_angle_increment);
}
slam.printMap();
return 0;
}
代码解释:
- 定义了
Pose
结构体来表示机器人的位置和朝向。 RobotSLAM
类包含机器人的当前Pose
以及存储地图的map
向量。move
函数根据线速度和角速度更新机器人的位置和朝向,使用std::cos
和std::sin
函数将线速度转换为x
和y
方向的位移。sense
函数模拟激光雷达的测量,使用std::normal_distribution
生成带有噪声的测量值。updateMap
函数根据测量更新地图,将测量点转换为全局坐标,这里使用std::cos
和std::sin
函数根据角度和测量距离计算全局坐标。printMap
函数打印地图中的所有点。
在 main
函数中,模拟了机器人的运动和测量更新,使用 cmath
中的函数完成机器人的运动学计算和测量点的坐标转换,逐步构建环境地图。这个例子展示了 cmath
在机器人 SLAM 中用于位置更新、传感器测量和地图构建等方面的综合应用,这些函数为机器人的运动和环境感知提供了必要的数学计算支持。