← 目录 / 第二章 · 变量与数据类型 / 2.4 cmath 数学库

2.4 cmath 数学库

<cmath> 内置了许多常用的数学计算函数,覆盖取整、绝对值、幂运算和三角函数等竞赛常用场景。

cmath 数学库

<cmath> 内置了许多常用的数学计算函数,覆盖取整、绝对值、幂运算和三角函数等竞赛常用场景,使用前需要先引入头文件 #include <cmath>

2.4.1 为什么需要数学函数库

像"求平方根"这样的运算,如果没有现成的函数,自己写代码实现并不简单——你可能需要用二分查找或者牛顿迭代法一步步逼近答案,还要处理各种边界情况。<cmath> 把这些数学上成熟、经过反复优化的算法都封装成了现成的函数,你只需要"调用",不需要"重新发明"。

这就像箱子里已经有一把量角器和一把尺子,你不需要自己动手做——拿来用就好。养成"先想想标准库里有没有现成函数"的习惯,能省下大量调试时间。

📐
使用前提:所有函数使用前都要在文件开头写上 #include <cmath>。绝大多数函数接收 double 类型的参数、返回 double 类型的结果,即使你传入的是整数,也会被隐式转换成 double 参与计算(见 2.1 节)。

2.4.2 取整函数:floor · ceil · round

这三个函数都是把小数变成整数,但"往哪个方向靠"完全不同,是初学者最容易混淆的一组函数。可以把它们想象成三种不同性格的"取整方式":

floor(x) 向下取整——永远朝"更小"(数轴上更靠左)的方向靠,即"不大于 x 的最大整数"。
ceil(x) 向上取整——永远朝"更大"(数轴上更靠右)的方向靠,即"不小于 x 的最小整数"。
round(x) 四舍五入——就近取整,小数部分正好是 0.5 时,朝"远离 0"的方向取整。
函数功能说明示例结果
floor(x) 向下取整(不大于 x 的最大整数) floor(1.91) 1
floor(x) 负数同理,继续朝更小的方向靠 floor(-1.5) -2
ceil(x) 向上取整(不小于 x 的最小整数) ceil(1.123) 2
ceil(x) 负数同理,继续朝更大的方向靠 ceil(-1.5) -1
round(x) 四舍五入为最近整数(C++11) round(1.5) 2
round(x) 负数的 0.5 也是"远离 0"取整,不是"向下" round(-1.5) -2
⚠️
负数容易搞反:floor(-1.5) 得到 -2 而不是 -1,因为 -2 才是"更小"的那个数;ceil(-1.5) 得到 -1 而不是 -2,因为 -1 才是"更大"的那个数。记住口诀——floor 永远变小,ceil 永远变大,和正负号无关。

2.4.3 绝对值与幂运算:abs · pow · sqrt

函数功能说明示例结果
abs(x) 返回 x 的绝对值(C++11 起同时支持整数和浮点数) abs(-5) 5
fabs(x) 浮点数 x 的绝对值(C 语言遗留,C++11 后可直接用 abs) fabs(-3.14) 3.14
pow(x, y) 返回 x 的 y 次幂(返回 double) pow(2, 3) 8
sqrt(x) 返回 x 的算术平方根(返回 double) sqrt(9) 3

powsqrt 有一个共同点:无论传入的是整数还是浮点数,返回值永远是 double。这是因为幂运算和开方的结果很可能不是整数(比如 sqrt(2) 是无限不循环小数),函数没办法提前知道结果会不会"恰好整除",所以统一按 double 处理,交给你自己决定要不要转换回整数。

📖
C++11 中 abs 的改进:C++11 起,<cmath> 中的 abs 已针对 doublefloatlong double 做了重载,可以直接对浮点数使用 abs(),不再需要单独用 fabs()。绝大多数现代 OJ 平台支持 C++11,直接用 abs 即可。

2.4.4 三角函数:sin · cos · tan

C++ 的三角函数使用弧度制,不是我们日常习惯的角度制——这是初学者最容易踩的坑。弧度和角度的换算关系是:

180° = π 弧度(约 3.14159 弧度),也就是说角度要先乘以 π / 180 才能变成弧度,才能交给 sincostan 使用。
函数功能说明示例结果
sin(x) 计算 x(弧度制)的正弦值 sin(0) 0
cos(x) 计算 x(弧度制)的余弦值 cos(0) 1
tan(x) 计算 x(弧度制)的正切值 tan(0) 0
💡
竞赛小技巧:C++ 标准并不保证一定提供 M_PI 这个 π 常量(它属于编译器扩展,不同平台表现不一致)。竞赛中更稳妥的做法是自己算一次:const double PI = acos(-1.0);——因为 cos(π) = -1,反过来 acos(-1) 就精确等于 π,不需要手写一长串小数。

2.4.5 综合示例

C++ · cmath 综合示例
1#include <iostream>
2#include <cmath>
3using namespace std;
4
5int main()
6{
7 cout << abs(-42) << endl; // 42
8 cout << floor(4.9) << endl; // 4
9 cout << ceil(4.1) << endl; // 5
10 cout << round(4.5) << endl; // 5
11 cout << pow(2, 8) << endl; // 256
12 cout << sqrt(16) << endl; // 4
13
14 // 角度转弧度,再求正弦值
15 const double PI = acos(-1.0);
16 double deg = 90;
17 double rad = deg * PI / 180;
18 cout << sin(rad) << endl; // sin(90°) = 1
19 return 0;
20}

2.4.6 常见陷阱与易错点

把本节内容汇总成几条最容易踩坑的规则:

1
浮点精度陷阱:powsqrt 返回 double 类型,赋值给整数时可能因浮点误差出错。例如 int x = sqrt(25) 理论上得 5,但浮点精度问题可能让底层实际算出 4.999999...,转换成 int 时直接截断,变成 4安全做法:int x = (int)round(sqrt(25));,先四舍五入抹平误差,再转换成整数。
2
round 对负数是"远离 0",不是"向下":round(-1.5) 的结果是 -2,很多初学者会误以为四舍五入永远是"往下取",其实规则是"往数值更大的那一侧的相反方向"——准确说是往远离 0 的方向凑整。
3
忘记把角度转成弧度:直接把角度值(比如 90)传给 sincostan 是最常见的错误之一,函数不会报错,但会安安静静地返回一个完全错误的结果。使用前一定要先乘以 π / 180
4
大数场景下 pow 可能不精确:pow 内部是按浮点数计算的,当指数很大、结果超出 double 能精确表示的整数范围(约 2⁵³)时,返回的结果可能有偏差。如果需要计算大整数的精确幂(尤其是配合取模的场景),应该自己手写"快速幂",而不是依赖 pow