NOI C++ 课程体系 / 语法入门 / 第8讲
CSP-J 入门级 · 语法入门 · 数学库函数专题

C++ 数学库函数 完全指南

让程序拥有"数学大脑" —— 绝对值、四舍五入、取整、平方根、三角函数、对数、指数,八大常用函数逐一讲透,#include <cmath> 之后一切尽在掌握。

6 大教学模块 8 大库函数精讲 6 个精讲案例 5 大易错点 1 张速查表 15 道分层练习
本讲 · 第 12/56 讲数学库函数
模块 01

情景导航

先用"天文台计算器"的故事建立直觉,再用生活类比看清八大数学库函数的本质,最后给出函数调用的准确定义和一句好记的口诀。

故事故事引入 —— 天文台的计算器

暑假,小强跟着天文社的张老师来到山顶天文台观测流星雨。张老师打开笔记本电脑,屏幕上满是密密麻麻的公式和数字。小强好奇地凑过去看:

张老师先输入了一个角度值,按下 "sin" 键,屏幕上立刻跳出了正弦值——"看,这是 三角函数,帮你算角度和边长的关系。"

接着张老师又按了 "sqrt",输入 144,屏幕上显示 12。"这是 平方根函数,求一个非负数的平方根,144 的平方根就是 12。"

小强问:"那如果我要算 3 的 5 次方呢?"张老师笑着输入 "pow(3, 5)",得到 243。"这是 指数函数,pow(x, y) 就是求 x 的 y 次方。"

最让小强惊讶的是,张老师输入 -27.8,按下 "abs",结果变成 27.8;再输入 3.14,按下 "round",结果还是 3;按下 "floor" 得 3,按下 "ceil" 得 4。"这些是 取整和绝对值函数,在科学计算中太常用了。"

小强恍然大悟:"原来计算机里也有这么多现成的数学工具,不用我们自己写算法去算!"

"绝对值、四舍五入、上下取整、平方根、三角函数、对数、指数 —— 八大数学库函数,让程序秒变科学计算器!"

张老师点点头:"不过要用这些函数,得先记住一个关键——在程序开头写上 #include <cmath>,告诉编译器你要用数学库。不然编译器会'不认识'这些函数。"

💡 这个故事告诉我们什么?

天文台的场景虽然复杂,但背后都是数学计算。C++ 标准库提供了 <cmath> 头文件,里面封装了我们常用的数学函数,不需要自己从头写算法,直接调用即可。就像天文台不需要自己造望远镜一样,程序员也不需要自己写开平方、求对数的复杂算法。

C++ 里的数学库函数就像一个个"数学小助手",你告诉它一个数(参数),它告诉你结果(返回值)。每个函数有固定的名字、固定的参数个数和类型,用对了就事半功倍。

类比生活类比 —— 八大函数,八种工具

把八大数学库函数和身边的工具对一对号,抽象的函数名立刻变得亲切起来:

📝

绝对值 · abs / fabs

就像把"向左走 5 步"和"向右走 5 步"都统一成"走了 5 步",去掉正负号只看距离。

对应:abs(-5) = 5
📈

四舍五入 · round

就像考试算平均分,小数部分满 0.5 就进 1,不满就舍掉,取最接近的整数。

对应:round(3.6) = 4
⭙

下取整 · floor

就像楼层按钮,3.9 层按不到,只能到 3 楼——永远往小取整,取不超过它的最大整数。

对应:floor(3.9) = 3
⭚

上取整 · ceil

就像租船,3 个人坐不满 2 人船,得租 2 条——永远往大取整,取不小于它的最小整数。

对应:ceil(3.1) = 4
◼

平方根 · sqrt

就像已知正方形面积求边长,面积是 144,边长就是 sqrt(144) = 12。

对应:sqrt(144) = 12
☃

三角函数 · sin/cos/tan

就像测量旗杆高度,知道角度和距离,用三角函数就能算出高度,不用爬上去量。

对应:sin(angle)
📝

对数 · log / log10

就像地震震级、声音分贝,用对数把很大的数压缩成很小的数,方便比较。

对应:log10(1000) = 3
📦

指数 · pow / exp

就像细菌分裂,1 个变 2 个、2 个变 4 个……pow(2, n) 就是 2 的 n 次方,增长飞快。

对应:pow(2, 10) = 1024
定义什么是数学库函数

C++ 标准库在 <cmath> 头文件中提供了大量数学函数,使用前必须在文件顶部写 #include <cmath>。

调用函数的格式是:函数名(参数),例如 abs(-5) 就是调用绝对值函数,参数是 -5,返回值是 5。大多数数学函数接收 double 类型参数,返回 double 类型结果。

函数功能参数返回值例子
abs(x)绝对值整数intabs(-5) = 5
fabs(x)绝对值(浮点)doubledoublefabs(-3.14) = 3.14
round(x)四舍五入doubledoubleround(3.6) = 4.0
floor(x)下取整doubledoublefloor(3.9) = 3.0
ceil(x)上取整doubledoubleceil(3.1) = 4.0
sqrt(x)平方根double(x>=0)doublesqrt(144) = 12.0
sin(x)正弦double(弧度)doublesin(0) = 0.0
cos(x)余弦double(弧度)doublecos(0) = 1.0
tan(x)正切double(弧度)doubletan(0) = 0.0
log(x)自然对数(ln)double(x>0)doublelog(2.718) ≈ 1.0
log10(x)常用对数(log₁₀)double(x>0)doublelog10(1000) = 3.0
pow(x, y)x 的 y 次方double, doubledoublepow(2, 10) = 1024.0
exp(x)e 的 x 次方doubledoubleexp(1) ≈ 2.718

注意:C++ 中 abs(x) 用于整数绝对值,fabs(x) 用于浮点数绝对值。虽然现代编译器通常能自动选择正确的 abs,但写 fabs 更规范。

函数选用口诀 绝对值用 abs 或 fabs,正负去掉变正数;
四舍五入用 round,最近整数最靠谱;
下取整来 floor 帮,永远往小不往上;
上取整来 ceil 顶,永远往大不往下;
平方根用 sqrt 算,负数开方会报错;
三角函数 sin cos,参数弧度要记牢;
对数 log 是自然,log10 是常用;
指数 pow 次方算,exp 是 e 的幂。

口诀里藏着本课的全部八大函数家族。下面我们就把它们一个一个拆开,看清各自的"名字、参数、返回值和陷阱"。

模块 02

知识探究

八大数学库函数逐一拆解:绝对值与取整函数打地基,平方根与三角函数拓展几何,对数与指数函数处理增长与衰减,最后用一段动画看懂函数调用的求值过程。

1绝对值函数 —— abs 与 fabs

绝对值就是"去掉正负号"。在 C++ 中,整数用 abs(x),浮点数用 fabs(x)(floating-point absolute value)。两者功能一样,只是参数类型不同。

abs(-5) = 5     fabs(-3.14) = 3.14
abs(x):整数绝对值,参数和返回值都是 int fabs(x):浮点绝对值,参数和返回值都是 double -5 的绝对值是 5,0 的绝对值是 0 负数变正数,正数不变

使用绝对值函数,牢记两条规则:

规则说明
整数用 abs,浮点用 fabs虽然现代编译器通常能自动处理,但写 fabs 对 double 更规范
返回值一定是非负数abs(x) 的结果要么是正数,要么是 0,绝不可能是负数
C++绝对值函数演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << abs(-5) << " " << abs(3) << endl;
    cout << fabs(-3.14) << " " << fabs(2.71) << endl;
    return 0;
}
运行结果
5 3
3.14 2.71
2四舍五入函数 —— round

四舍五入是最常见的取整方式。C++ 的 round(x) 函数把 x 四舍五入到最接近的整数,返回值是 double 类型(带小数点)。

round(3.2) = 3.0     round(3.6) = 4.0
.5 及以上就进 1 .4 及以下就舍掉 -3.6 四舍五入得 -4.0(注意负数方向) 返回值是 double,转 int 需强转
C++四舍五入演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << round(3.2) << " " << round(3.6) << endl;
    cout << round(-3.6) << " " << round(3.5) << endl;
    int n = int(round(3.8));
    cout << n << endl;
    return 0;
}
运行结果
3 4
-4 4
4

解读:round(3.5) 的结果是 4.0(.5 进 1);round(-3.6) 的结果是 -4.0(负数往远离 0 的方向取整)。用 int() 强转可以把 double 转成整数。

3下取整函数 —— floor

floor(x) 返回不超过 x 的最大整数,也就是"永远往小取整"。就像楼层按钮,3.9 楼按不到,只能到 3 楼。

floor(3.9) = 3.0     floor(-3.1) = -4.0
正数:舍掉小数部分 负数:也往小取(更小的方向) floor(3.0) = 3.0(整数不变) 返回值是 double

重点注意:floor(-3.1) 不是 -3,而是 -4!因为 -4 是不超过 -3.1 的最大整数(-4 < -3.1 < -3)。

C++下取整演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << floor(3.9) << " " << floor(-3.1) << endl;
    cout << floor(5.0) << " " << floor(5.5) << endl;
    return 0;
}
运行结果
3 -4
5 5
4上取整函数 —— ceil

ceil(x) 返回不小于 x 的最小整数,也就是"永远往大取整"。就像租船,3 个人坐 2 人船,得租 ceil(3/2) = 2 条。

ceil(3.1) = 4.0     ceil(-3.9) = -3.0
正数:小数部分进 1 负数:也往大取(更接近 0 的方向) ceil(5.0) = 5.0(整数不变) 返回值是 double

对比记忆:floor 永远往小,ceil 永远往大,round 四舍五入。三个函数合在一起,取整方式就全了。

floor(下取整)
  • 永远往小取
  • floor(3.9) = 3
  • floor(-3.1) = -4
ceil(上取整)
  • 永远往大取
  • ceil(3.1) = 4
  • ceil(-3.9) = -3
C++上下取整对比
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double x = 3.7;
    cout << "floor: " << floor(x) << endl;
    cout << "round: " << round(x) << endl;
    cout << "ceil:  " << ceil(x) << endl;
    return 0;
}
运行结果
floor: 3
round: 4
ceil:  4

解读:3.7 的下取整是 3,四舍五入是 4,上取整也是 4。三个函数各有用途,选哪个取决于你的需求。

口诀:floor 往小 floor 住,ceil 往大 ceil 起来,round 四舍五入最公平。
5平方根函数 —— sqrt

sqrt(x) 返回 x 的非负平方根。数学上记作 √x,在 C++ 中写成 sqrt(x)。要求 x 必须是非负数(x >= 0),否则返回 NaN(Not a Number)。

sqrt(144) = 12.0     sqrt(2) ≈ 1.41421
sqrt(x) 要求 x >= 0 返回值是 double sqrt(0) = 0 sqrt(x) * sqrt(x) 不一定精确等于 x(精度问题)

使用 sqrt 时注意:如果参数是负数,结果会是 NaN(不是一个有效的数字),在判断时需要先检查参数是否合法。

C++平方根函数演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << sqrt(144) << " " << sqrt(2) << endl;
    cout << sqrt(0) << " " << sqrt(0.25) << endl;
    int n = int(sqrt(16));
    cout << n << endl;
    return 0;
}
运行结果
12 1.41421
0 0.5
4
6三角函数 —— sin / cos / tan

C++ 的三角函数 sin(x)、cos(x)、tan(x) 的参数和返回值都是 double 类型。最重要的规则是:参数必须用弧度(radian),不能用角度(degree)。

弧度和角度的转换公式:

转换方向公式
角度转弧度弧度 = 角度 * 3.14159265358979 / 180.0
弧度转角度角度 = 弧度 * 180.0 / 3.14159265358979

C++ 中没有内置的 PI 常量,通常用 3.14159265358979 或 acos(-1.0) 来表示 π。

C++三角函数演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    const double PI = 3.14159265358979;
    double angle = 30;  // 30 度
    double rad = angle * PI / 180.0;  // 转弧度
    cout << "30度(弧度:" << rad << ")" << endl;
    cout << "sin(30度) = " << sin(rad) << endl;
    cout << "cos(30度) = " << cos(rad) << endl;
    cout << "tan(30度) = " << tan(rad) << endl;
    return 0;
}
运行结果
30度(弧度:0.523599)
sin(30度) = 0.5
cos(30度) = 0.866025
tan(30度) = 0.57735

解读:sin(30°) = 0.5 是数学常识,验证了弧度转换的正确性。记住:调用 sin/cos/tan 之前,先把角度转成弧度!

7对数函数 —— log 与 log10

C++ 提供两种对数函数:log(x) 是自然对数(以 e 为底,记作 ln x),log10(x) 是以 10 为底的对数。两者都要求 x > 0。

log(x) = ln(x) log10(x) = log₁₀(x)
log(x):自然对数,底是 e ≈ 2.718 log(2.718) ≈ 1 log10(x):常用对数,底是 10 log10(1000) = 3,因为 10³ = 1000

如果需要用其他底的对数,可以用换底公式:log_b(x) = log(x) / log(b) 或 log_b(x) = log10(x) / log10(b)。

C++对数函数演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << "log(e) = " << log(2.718281828) << endl;
    cout << "log10(1000) = " << log10(1000) << endl;
    // 换底公式:log₂(8) = log(8) / log(2)
    cout << "log₂(8) = " << log(8) / log(2) << endl;
    return 0;
}
运行结果
log(e) = 1
log10(1000) = 3
log₂(8) = 3
8指数函数 —— pow 与 exp

pow(x, y) 返回 x 的 y 次方(x^y),exp(x) 返回 e 的 x 次方(e^x)。两者都返回 double 类型。

pow(2, 10) = 1024.0     exp(1) ≈ 2.71828
pow(x, y):x 的 y 次方 exp(x):e 的 x 次方,等价于 pow(e, x) pow(2, -3) = 0.125(负指数 = 倒数) pow(0, 0) = 1(数学上约定)

pow 的指数 y 可以是小数,此时 pow(4, 0.5) 等价于 sqrt(4) = 2。但用 sqrt 更直观,建议开平方时直接用 sqrt。

C++指数函数演示
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << pow(2, 10) << " " << pow(3, 3) << endl;
    cout << pow(2, -3) << " " << exp(1) << endl;
    cout << pow(4, 0.5) << " " << sqrt(4) << endl;
    return 0;
}
运行结果
1024 27
0.125 2.71828
2 2

解读:pow(2, 10) = 1024 表示 2 的 10 次方;pow(2, -3) = 0.125 表示 1/8;pow(4, 0.5) = 2 和 sqrt(4) 结果一致。

9串起来看:函数调用的求值之旅

函数调用就像"传话游戏":你把参数传给函数,函数算出结果返回给你。跟着动画看一个复杂表达式的求值过程:

🎬 动画演示:表达式求值过程

1
表达式:y = round(sqrt(2) * 10) + abs(-3)
2
先算最里面的函数:sqrt(2) ≈ 1.41421,表达式变成 y = round(1.41421 * 10) + abs(-3)
3
算乘法:1.41421 * 10 = 14.1421,表达式变成 y = round(14.1421) + abs(-3)
4
算 round(14.1421) = 14.0,算 abs(-3) = 3,表达式变成 y = 14.0 + 3
5
最后算加法:14.0 + 3 = 17.0,所以 y = 17.0

解读:函数调用就像剥洋葱,从最里面的一层开始算。先算参数,再算函数,最后算外层的运算符。嵌套调用时,"里层先算"是铁律。

案例6 个由浅入深的案例

案例 1:温度转换 —— 取整函数的实战

题目:输入一个摄氏温度(double),分别输出它的华氏温度(四舍五入取整),以及用 floor 和 ceil 取整后的华氏温度。

华氏温度公式:F = C × 9/5 + 32

C++温度转换
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double c;
    cin >> c;
    double f = c * 9.0 / 5.0 + 32;
    cout << "原始华氏温度: " << f << endl;
    cout << "四舍五入: " << round(f) << endl;
    cout << "下取整:    " << floor(f) << endl;
    cout << "上取整:    " << ceil(f) << endl;
    return 0;
}
运行结果
输入:37.5
输出:
原始华氏温度: 99.5
四舍五入: 100
下取整:    99
上取整:    100

解读:37.5°C = 99.5°F。四舍五入和上取整都是 100,下取整是 99。三种取整方式各有用途,选哪个取决于你的业务逻辑。

案例 2:圆的相关计算 —— sqrt 与三角函数联手

题目:输入圆的半径 r,计算圆的面积、周长,以及半径为 r 的圆的内接正三角形的面积。

圆面积 = π × r²,周长 = 2 × π × r,正三角形面积 = (√3 / 4) × (r × √3)²

C++圆的计算
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    const double PI = 3.14159265358979;
    double r;
    cin >> r;
    double area = PI * r * r;
    double perimeter = 2 * PI * r;
    double tri_area = (sqrt(3) / 4) * (r * sqrt(3)) * (r * sqrt(3));
    cout << area << " " << perimeter << " " << tri_area << endl;
    return 0;
}
运行结果
输入:5
输出:78.5398 31.4159 32.476

解读:sqrt(3) 用数学库函数计算,而不是手敲 1.73205...。用库函数的好处是精度更高,而且代码可读性更好。

案例 3:复利计算 —— pow 函数的理财实战

题目:输入本金 P、年利率 r(小数形式)、投资年数 n,计算 n 年后的本息总额。复利公式:A = P × (1 + r)^n

C++复利计算器
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double P, r;
    int n;
    cin >> P >> r >> n;
    double A = P * pow(1 + r, n);
    cout << "本金: " << P << endl;
    cout << "年利率: " << r * 100 << "%" << endl;
    cout << "年数: " << n << endl;
    cout << "本息总额: " << round(A * 100) / 100 << endl;
    return 0;
}
运行结果
输入:10000 0.05 10
输出:
本金: 10000
年利率: 5%
年数: 10
本息总额: 16288.95

解读:pow(1 + 0.05, 10) 计算 (1.05)^10,这是复利公式的核心。round(A * 100) / 100 用来保留两位小数,模拟货币精度。

案例 4:角度与弧度转换 —— 三角函数的必备工具

题目:输入一个角度值(度),输出它的弧度值、正弦值、余弦值和正切值。

C++角度转弧度并计算三角函数
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    const double PI = 3.14159265358979;
    double angle_deg;
    cin >> angle_deg;
    double rad = angle_deg * PI / 180.0;
    cout << "角度: " << angle_deg << "°" << endl;
    cout << "弧度: " << rad << endl;
    cout << "sin:  " << sin(rad) << endl;
    cout << "cos:  " << cos(rad) << endl;
    cout << "tan:  " << tan(rad) << endl;
    return 0;
}
运行结果
输入:45
输出:
角度: 45°
弧度: 0.785398
sin:  0.707107
cos:  0.707107
tan:  1

解读:45° 的 sin 和 cos 都是 √2/2 ≈ 0.707,tan 是 1。记住几个特殊角的值,考试和竞赛都能快速验证结果。

案例 5:取整函数大比拼 —— floor / round / ceil 三兄弟

题目:输入一个 double 值,分别用 floor、round、ceil 三种方式取整,并输出结果。再讨论一个实际场景:租船问题。

C++取整函数大比拼
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double x;
    cin >> x;
    cout << "floor: " << floor(x) << endl;
    cout << "round: " << round(x) << endl;
    cout << "ceil:  " << ceil(x) << endl;
    // 租船问题:n 个人,每条船最多坐 4 人,最少需要几条船?
    int n, per_boat = 4;
    cin >> n;
    int boats = int(ceil(n / double(per_boat)));
    cout << "最少需要 " << boats << " 条船" << endl;
    return 0;
}
运行结果(两次运行对比)
输入 3.7 → floor: 3, round: 4, ceil: 4
输入 10 人 → 最少需要 3 条船(ceil(10/4) = ceil(2.5) = 3)

解读:租船问题用 ceil 最合适——只要有余数就得多加一条船。注意 n / 4 要转成 double 再除以 per_boat,否则整数除法会先丢掉小数部分。

案例 6:现场捉虫 —— 三处高频错误

题目:下面这段程序想计算一个数学表达式,却藏着三处错误,你能全部找出来吗?

C++待捉虫的程序
#include <iostream>
// 忘记 #include <cmath>
using namespace std;
int main()
{
    double x = -5;
    cout << abs(x) << " ";          // 错误一
    cout << sqrt(-4) << " ";         // 错误二
    cout << sin(30) << " ";         // 错误三
    return 0;
}
错误问题所在修正方法
错误一忘记 #include <cmath>,编译器不认识 abs在文件顶部加上 #include <cmath>
错误二sqrt 参数为负数 -4,返回 NaN(非数字)调用前先判断参数是否 >= 0
错误三sin(30) 传入的是 30 弧度而不是 30 度先转弧度:sin(30 * PI / 180.0)

解读:这三处错误分别对应"忘写头文件""参数不合法""角度未转弧度"三大陷阱,后面的易错点环节还会逐个细讲。

模块 03

实践应用

三道动手题:跟踪函数调用的输出、捉出三处函数使用错误、综合运用多个数学库函数写一个小程序。

实践 1 写输出

题目:下面程序输出什么?

C++待跟踪的程序
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << round(3.14) << " ";
    cout << floor(-3.14) << " ";
    cout << ceil(4.001) << " ";
    cout << abs(int(-7)) << endl;
    return 0;
}
提示:逐个函数分析:round 四舍五入,floor 下取整,ceil 上取整,abs 绝对值。
点击查看参考答案
答案:3 -4 5 7
过程:round(3.14) = 3(.14 舍掉);floor(-3.14) = -4(往更小的方向取整);ceil(4.001) = 5(有非零小数就进 1);abs(-7) = 7(去掉负号)。
点评:注意 floor(-3.14) = -4 不是 -3!floor 永远往小取,负数方向"小"意味着更负。
实践 2 捉虫挑战

题目:下面三行代码各藏着一处错误,请找出来并改正。

C++三处虫子
#include <iostream>
// 忘记 #include <cmath>
using namespace std;
int main()
{
    cout << sqrt(-9) << endl;     // 第一处
    cout << sin(90) << endl;      // 第二处
    cout << log(-5) << endl;      // 第三处
    return 0;
}
提示:想一想每个函数的参数有什么要求?sin 的参数应该是什么单位?
点击查看参考答案
第一处:sqrt 的参数不能为负数,sqrt(-9) 返回 NaN。应在调用前判断参数是否 >= 0。
第二处:sin(90) 传入的是 90 弧度而不是 90 度。如果要算 90° 的正弦,应写成 sin(90 * PI / 180.0)。
第三处:log 的参数必须 > 0,log(-5) 返回 NaN。应在调用前判断参数是否 > 0。
实践 3 编程题

题目:简易科学计算器 —— 输入两个数 a 和 b,根据用户输入的操作符,执行对应的数学运算。

要求支持:求 a 的绝对值、求 a 的平方根、求 a 的 b 次方、求 a 的 b 次对数(用换底公式 log(a)/log(b))。

操作符用字符表示:'a' 绝对值,'s' 平方根,'p' 次方,'l' 对数。

提示:用 if-else 判断操作符,每个分支调用对应的数学库函数。sqrt 和 log 要检查参数合法性。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double a, b;
    char op;
    cin >> a >> b >> op;
    if (op == 'a') {
        cout << abs(int(a)) << endl;
    } else if (op == 's') {
        if (a >= 0) cout << sqrt(a) << endl;
        else cout << "参数不能为负" << endl;
    } else if (op == 'p') {
        cout << pow(a, b) << endl;
    } else if (op == 'l') {
        if (a > 0 && b > 0 && b != 1)
            cout << log(a) / log(b) << endl;
        else cout << "参数不合法" << endl;
    }
    return 0;
}
示例:输入 25 s → 输出 5;输入 2 10 p → 输出 1024;输入 1000 10 l → 输出 3。
点评:一个小程序把 abs、sqrt、pow、log 四个函数全用上了。参数合法性检查是科学计算程序的基本功,不能省。
模块 04

总结提升

一张表收拢八大数学库函数,一句口诀记住函数选用规则,再用"取整一题三解"体会不同函数的妙处。

总结核心要点总结
函数功能参数要求返回值一句话记住
abs(x)绝对值(整数)intint去掉正负号
fabs(x)绝对值(浮点)doubledouble浮点版绝对值
round(x)四舍五入doubledouble.5 及以上进 1
floor(x)下取整doubledouble永远往小取
ceil(x)上取整doubledouble永远往大取
sqrt(x)平方根double (x>=0)double负数开方会报错
sin/cos/tan三角函数double(弧度)double角度要先转弧度
log(x)自然对数 lndouble (x>0)double底是 e
log10(x)常用对数 log₁₀double (x>0)double底是 10
pow(x,y)x 的 y 次方double, doubledouble次方运算万能工具
exp(x)e 的 x 次方doubledouble等价于 pow(e, x)
函数选用口诀 绝对值用 abs 或 fabs,正负去掉变正数;
四舍五入用 round,最近整数最靠谱;
下取整来 floor 帮,永远往小不往上;
上取整来 ceil 顶,永远往大不往下;
平方根用 sqrt 算,负数开方会报错;
三角函数 sin cos,参数弧度要记牢;
对数 log 是自然,log10 是常用;
指数 pow 次方算,exp 是 e 的幂。

补充两条细节:所有数学函数都定义在 <cmath> 头文件中,忘记 #include <cmath> 是最高频的错误;调用三角函数前,务必把角度转成弧度。

拓展拓展案例 —— 取整的一题三解

同样是"把 3.7 变成整数 4",可以用三种不同的方式实现:

C++一题三解:取整为 4
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double x = 3.7;
    // 解法一:ceil 上取整(最简单直接)
    cout << int(ceil(x)) << " ";
    // 解法二:round 四舍五入(.5 及以上进 1)
    cout << int(round(x)) << " ";
    // 解法三:floor + 判断小数部分
    int result = int(floor(x));
    if (x - result >= 0.5) result++;
    cout << result << endl;
    return 0;
}
运行结果
4 4 4

解读:解法一用 ceil 最简单,解法二用 round 最直观,解法三展示了"手动实现四舍五入"的逻辑。实际写程序时优先用库函数,既简洁又不容易出错。但理解手动实现的逻辑,有助于深入理解函数的行为。

🧠 思考与启发

数学库函数是程序员的"数学工具箱",有了它们,你不需要自己写开平方、求对数的复杂算法,直接调用即可。就像建筑师不需要自己炼钢一样,程序员不需要自己实现数学公式。

想一想:为什么 C++ 的三角函数参数要用弧度而不用角度?提示:弧度的定义是"弧长等于半径的弧所对的圆心角",它和圆的几何性质天然契合,用弧度写公式更简洁。再想想:pow(-2, 3) 和 pow(-2, 2.5) 的结果有什么不同?为什么?(提示:偶次方根和奇次方根的区别)把这两个问题的答案记在心里,下一讲"数组"会让这些函数在批量数据处理中大显身手。

模块 05

学习检测

5 个最容易丢分的函数使用陷阱、一张考前必背速查表,以及可以贴在文具盒上的知识点速记卡。

易错 1

忘记 #include <cmath>:编译器不认识函数

使用任何数学库函数之前,必须在文件顶部写 #include <cmath>。忘记写这行,编译器会报"函数未声明"的错误。这是最高频的错误,没有之一。

错误写法
#include <iostream>
// 忘记 #include <cmath>
using namespace std;
int main() {
    cout << sqrt(16) << endl;  // 编译报错
}
正确写法
#include <iostream>
#include <cmath>
using namespace std;
int main() {
    cout << sqrt(16) << endl;  // 正确
}
口诀:用数学函数先记牢,#include cmath 不能少。
易错 2

sqrt 和 log 参数不合法:负数开方、零或负数取对数

sqrt(x) 要求 x >= 0,log(x) 和 log10(x) 要求 x > 0。传入非法参数不会报错,而是返回 NaN(Not a Number),后续计算全部被污染。

错误写法
double r = sqrt(-4);  // 返回 NaN
double l = log(-5);   // 返回 NaN
正确写法
if (x >= 0) cout << sqrt(x);
if (x > 0) cout << log(x);
口诀:开方对数先检查,参数合法再调用。
易错 3

三角函数参数用角度不用弧度

sin(30) 传入的是 30 弧度,不是 30 度!30 弧度 ≈ 1719°,结果和 sin(30°) = 0.5 完全不同。调用三角函数前,务必先转弧度。

错误写法
cout << sin(30);  // 30 弧度,不是 30 度
正确写法
const double PI = 3.14159265358979;
cout << sin(30 * PI / 180.0);  // 30 度转弧度
口诀:三角函数用弧度,角度先转再调用。
易错 4

floor 对负数的取整方向搞反

floor(-3.1) 不是 -3,而是 -4!因为 floor 永远往"更小"的方向取整,而 -4 < -3.1 < -3,所以 floor(-3.1) = -4.0。

易错理解
floor(-3.1) = -3  // 错误!
正确理解
floor(-3.1) = -4  // 正确!
// -4 是不超过 -3.1 的最大整数
口诀:floor 永远往小走,负数方向更负。
易错 5

round 返回值是 double,强转 int 时丢精度

round(x) 返回的是 double 类型(如 4.0),如果直接赋给 int 变量会截断小数部分。虽然 round 的结果本来就是整数,但类型转换时最好显式强转,避免后续运算时出现意外的类型提升。

易错理解
int n = round(3.7);  // 可以但不规范
// round 返回 double,隐式转换
推荐写法
int n = int(round(3.7));  // 显式强转
// 意图清晰,不会混淆
口诀:round 返回 double,强转 int 要显式。
速查考前速查表
类别函数示例提醒
绝对值abs(x) / fabs(x)abs(-5) = 5整数用 abs,浮点用 fabs
四舍五入round(x)round(3.6) = 4返回值是 double
下取整floor(x)floor(-3.1) = -4永远往小取
上取整ceil(x)ceil(3.1) = 4永远往大取
平方根sqrt(x)sqrt(144) = 12x 必须 >= 0
三角函数sin/cos/tansin(PI/6) = 0.5参数必须是弧度
对数log(x) / log10(x)log10(1000) = 3x 必须 > 0
指数pow(x,y) / exp(x)pow(2,10) = 1024exp(x) = e^x
头文件#include <cmath>必须写忘记写就报错
📌知识点速记卡
abs 与 fabs

abs 用于整数,fabs 用于浮点数。两者功能相同,都是去掉正负号。

round 四舍五入

.5 及以上进 1,.4 及以下舍掉。返回值是 double,转 int 需强转。

floor 下取整

永远往小取。floor(3.9)=3,floor(-3.1)=-4。注意负数方向。

ceil 上取整

永远往大取。ceil(3.1)=4,ceil(-3.9)=-3。租船问题首选。

sqrt 开平方

参数必须 >= 0,返回 double。sqrt(0)=0,负数返回 NaN。

三角函数用弧度

sin/cos/tan 参数必须是弧度。角度转弧度:angle * PI / 180。

log 是自然对数

log(x) = ln(x),log10(x) = log₁₀(x)。换底公式:log_b(x) = log(x)/log(b)。

pow 和 exp

pow(x,y) = x^y,exp(x) = e^x。exp(x) 等价于 pow(e, x)。

课后练习

练习作业

巩固八大数学库函数的使用规则,分层练习,点击展开答案与解析。

总结练习3 道综合题
总结 1 写输出

题目:下面两行代码输出什么?
#include <cmath>>
cout << round(3.5) << " " << floor(-2.7);

提示:round 四舍五入,floor 下取整。注意 floor 对负数的方向。
点击查看参考答案
答案:4 -3。round(3.5) = 4(.5 进 1);floor(-2.7) = -3(-3 是不超过 -2.7 的最大整数)。
总结 2 判断题

题目:判断 —— ceil(5.0) 的返回值是整数 5。

提示:ceil 的返回值类型是什么?
点击查看参考答案
答案:错误。ceil(5.0) 的返回值是 double 类型的 5.0,不是 int 类型的 5。虽然数值相同,但类型不同。
总结 3 编程题

题目:输入一个正整数 n,计算并输出:n 的绝对值、n 的平方根(保留 3 位小数)、以 2 为底 n 的对数(log₂n)(用 log2 换底公式计算)。

提示:log₂(n) = log(n) / log(2)。注意 abs 的参数类型。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
    int n;
    cin >> n;
    cout << abs(n) << " ";
    cout << fixed << setprecision(3) << sqrt(n) << " ";
    cout << int(log(n) / log(2)) << endl;
    return 0;
}
示例:输入 16 → 输出 16 4.000 4。说明:log₂(16) = 4,因为 2⁴ = 16。log(n)/log(2) 用换底公式计算以 2 为底的对数。
A 组基础巩固(4 题)
A1 填空题

题目:round(4.3) 的结果是 ______;floor(-5.8) 的结果是 ______;ceil(5.1) 的结果是 ______。

点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main(){
    cout << round(4.3) << endl;    // 4  :四舍五入,.3 舍去
    cout << floor(-5.8) << endl;   // -6 :向下取整,取更小的整数
    cout << ceil(5.1) << endl;     // 6  :向上取整,有非零小数就进 1
    return 0;
}
// 实际输出:
// 4
// -6
// 6

答案:4;-6;6。

思路:三个函数都改不了"方向",只是名字不同:round 是四舍五入,看小数第一位;floor 是"地板",永远往数轴左边(更小)找整数;ceil 是"天花板",永远往数轴右边(更大)找整数。负数是分水岭——floor(-5.8) 往更小走得到 -6,而 ceil(5.1) 往更大走得到 6。

考点:round / floor / ceil 三个取整函数的语义差别,对应本讲"取整函数"一节。记忆法:floor 地板在下、ceil 天花板在上,别被正负号带偏。

易错:① 负数取整出错,把 floor(-5.8) 写成 -5(那是 ceil 的结果);② 认为 ceil(5.1) 还是 5,忘了"只要有非零小数就进 1";③ round 与 floor 混用,round(4.3) 写成 5;④ 忘了 #include <cmath>,编译时报"找不到标识符"。

A2 填空题

题目:C++ 中调用数学库函数需要 #include ______ 头文件;log10(10000) 的结果是 ______。

点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>                  // ← 这里填 <cmath>:数学库函数都在它里面
using namespace std;
int main(){
    cout << log10(10000) << endl;
    // log10 是以 10 为底的对数:10 的多少次方等于 10000?
    // 10^4 = 10000,所以结果是 4
    return 0;
}
// 实际输出:4

答案:<cmath>;4。

思路:头文件是死记的:C++ 把所有数学函数(sqrt、pow、abs、log10、sin……)统一放在 cmath 里,就像把工具箱放在同一个抽屉。求对数不要硬算,反过来问自己:"10 要乘几次自己才能变成 10000?"答案是 4 次,所以 log₁₀(10000) = 4。

考点:cmath 头文件与对数函数 log10 / log,对应本讲"头文件与常用数学函数"一节。常用结论:log₁₀(10ⁿ) = n;求一个十进制数的位数时,位数 = floor(log₁₀(n)) + 1。

易错:① 头文件写成 <math.h>(C 语言写法的旧名字,竞赛一般用 C++ 的 cmath);② 把 log10 当成自然对数,算成别的值——自然对数是 log 或 log10 的区分要记清;③ 答成 10 或 10000,忘了对数就是"求指数";④ 忘记 log10(1) = 0、log10(0) 是负无穷大这种边界情况。

A3 写输出

题目:下面代码输出什么?
#include <cmath>>
cout << abs(-7) << " " << fabs(-2.5);

提示:abs 和 fabs 都是取绝对值,只是参数类型不同。
点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>
#include <cstdlib>              // abs 的整数版本在这里
using namespace std;
int main(){
    cout << abs(-7) << " ";     // 7   :整数绝对值
    cout << fabs(-2.5) << endl; // 2.5 :浮点数绝对值
    return 0;
}
// 实际输出:7 2.5

答案:7 2.5。

思路:两个函数干的是同一件事——把负号抹掉,区别只在参数类型。abs 面向整数,返回整数 7;fabs 面向浮点数(float/double),返回 2.5。输出 2.5 而不是 2,正是因为 fabs 保留小数部分。

考点:abs 与 fabs 的参数类型与返回值,对应本讲"绝对值函数"一节。一句话:整数用 abs,小数用 fabs,别用反。

易错:① 用 abs 处理小数导致精度丢失,abs(-2.5) 得到 2;② 误以为 fabs 会四舍五入成 3;③ 只 #include <cmath> 就想直接用整数版 abs,某些编译器会报错——保险做法是同时包含 <cstdlib>;④ 忘了绝对值只是"抹负号",fabs(2.5) 仍然是 2.5,不是 -2.5。

A4 填空题

题目:pow(3, 4) 的值是 ______;exp(0) 的值是 ______;sqrt(0.25) 的值是 ______。

点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main(){
    cout << pow(3, 4) << " ";      // 81 :3^4 = 3 × 3 × 3 × 3
    cout << exp(0) << " ";         // 1  :e^0 = 1(任何数的 0 次方都是 1)
    cout << sqrt(0.25) << endl;    // 0.5:√0.25
    return 0;
}
// 实际输出:81 1 0.5

答案:81;1;0.5。

思路:pow(底数, 指数) 就是乘方,3⁴ = 3×3×3×3 = 81。exp 是以自然常数 e 为底的指数函数,e⁰ = 1——任何非零数的 0 次方都是 1,别被 e 吓到。sqrt 是开平方,0.5 × 0.5 = 0.25,所以 √0.25 = 0.5。

考点:幂函数 pow、指数函数 exp、平方根 sqrt 的用法与常见特殊值,对应本讲"幂与开方"一节。这里也是海伦公式、两点间距离等题目的基础。

易错:① 把 pow 的返回类型当整数——cout << pow(3, 4) 输出 81(因为结果显示为整数形式),但它的真实类型是 double,做整数运算时要当心精度;② 负指数理解错,以为 pow(2, -3) = -8,其实是 1/8 = 0.125;③ sqrt 传负数,如 sqrt(-1),会得到 nan(非数字);④ 把 exp(0) 算成 0或 e。

B 组能力提升(4 题)
B1 写输出

题目:下面程序输出什么?

C++待跟踪的程序
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    cout << floor(-3.9) << " ";
    cout << ceil(-3.1) << " ";
    cout << round(-2.5) << " ";
    cout << abs(int(-15)) << endl;
    return 0;
}
提示:逐个函数分析,注意 floor 和 ceil 对负数的方向。
点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
int main(){
    cout << floor(-3.9) << " ";     // -4:向更小方向取整
    cout << ceil(-3.1) << " ";      // -3:向更大方向取整
    cout << round(-2.5) << " ";     // -3:.5 时远离 0 进位
    cout << abs(int(-15)) << endl;  // 15:整数绝对值
    return 0;
}
// 实际输出:-4 -3 -3 15

答案:-4 -3 -3 15。

思路:逐个拆开算,重点盯负数。floor(-3.9) 找"地板",-3.9 左边最近的整数是 -4;ceil(-3.1) 找"天花板",-3.1 右边最近的整数是 -3。round(-2.5) 是 .5 的临界情况,C++ 规定遇到 .5 时"远离 0"进位,所以 -2.5 变成 -3(不是 -2)。最后 abs(int(-15)) 把整数 -15 的负号去掉,得 15。

考点:取整函数在负数上的方向,以及 round 的 .5 规则,对应本讲"取整函数"一节。round 遇 .5 远离 0 是本题最容易丢分的地方,和小时候"四舍五入"的直觉有细微差别。

易错:① 把 round(-2.5) 算成 -2(按"银行家舍入"或凭直觉往近的偶数走),C++ 的 round 是 -3;② 负数 floor / ceil 方向搞反,floor(-3.9) 写成 -3;③ 把 abs 的参数写成 int(-15) 之外的形式,或者直接用 fabs 输出 15.0;④ 全部函数都忘了包含 <cmath>,直接用 floor 会编译报错。

B2 编程题

题目:输入一个三角形的三条边 a、b、c(double),用海伦公式计算三角形面积。海伦公式:s = (a+b+c)/2,面积 = sqrt(s*(s-a)*(s-b)*(s-c))。

提示:先算半周长 s,再代入海伦公式。sqrt 的参数必须非负,三角形三边一定满足条件。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double a, b, c;
    cin >> a >> b >> c;
    double s = (a + b + c) / 2.0;
    double area = sqrt(s * (s - a) * (s - b) * (s - c));
    cout << area << endl;
    return 0;
}
示例:输入 3 4 5 → 输出 6。说明:s = (3+4+5)/2 = 6,面积 = sqrt(6×3×2×1) = sqrt(36) = 6。海伦公式是求三角形面积的通用方法。

思路:先求出半周长 s,再代入海伦公式开平方得到面积。

易错:半周长用 2 做整数除法(要写成 2.0);三边构不成三角形时括号里会出现负数,sqrt 会算出 nan。

B3 写输出

题目:下面程序输出什么?(提示:先算弧度再算三角函数)

C++三角函数跟踪
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    const double PI = 3.14159265358979;
    cout << sin(0) << " ";
    cout << cos(0) << " ";
    cout << tan(PI / 4) << endl;
    return 0;
}
提示:sin(0) = 0,cos(0) = 1,tan(π/4) = 1。
点击查看参考答案
C++完整参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main(){
    const double PI = 3.14159265358979;
    cout << sin(0) << " ";        // 0:sin(0°) = 0
    cout << cos(0) << " ";        // 1:cos(0°) = 1
    cout << tan(PI / 4) << endl;  // 1:tan(45°) = 1
    return 0;
}
// 实际输出:0 1 1

答案:0 1 1。

思路:三角函数的角度要先换成弧度:180° 对应 π,所以 45° 就是 π/4。sin(0) = 0、cos(0) = 1 这两个直接背。tan(π/4) 用同一个直角三角形的"对边/邻边"理解,45° 时对边和邻边相等,比值是 1。(计算机里的 tan(π/4) 其实是 0.999999999999998,cout 默认取 6 位有效数字,四舍五入后显示 1。)

考点:sin / cos / tan 的参数是弧度制,对应本讲"三角函数"一节。常用特殊值:sin 30° = 0.5,cos 60° = 0.5,tan 45° = 1,sin 90° = 1,cos 90° = 0,这些都要背下来。

易错:① 直接把角度写进去,如 tan(45),得到的是 45 弧度的值(约 1.62),不是 1——必须写成 tan(45 * PI / 180) 或 tan(PI / 4);② 答成"0 1 0.999999...",其实 cout 默认精度就显示 1;③ 把 π 写成 3.14,精度不够会让计算结果出现可见误差;④ 忘了三角函数属于 <cmath> 需要包含头文件。

B4 判断题

题目:判断 —— pow(2, -3) 的结果是 -8。

提示:负指数是什么意思?pow(2, -3) = 1 / 2³ = ?
点击查看参考答案
答案:错误。pow(2, -3) = 1/8 = 0.125,不是 -8。负指数表示取倒数,不是取负数。

考点:pow 的指数为负数表示取倒数,2 的 -3 次方等于 1/8。

易错:以为负指数就是把结果变成负数,答成 -8。

C 组挑战拓展(4 题)
C1 编程题

题目:输入一个正整数 n,计算 n!(n 的阶乘)的位数。提示:log₁₀(n!) = log₁₀(1) + log₁₀(2) + ... + log₁₀(n),位数 = floor(log₁₀(n!)) + 1。

提示:不用循环算阶乘(会溢出),用对数的性质把乘法变成加法。log₁₀(n!) = Σ log₁₀(i)。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n;
    cin >> n;
    double sum = 0;
    for (int i = 1; i <= n; i++)
        sum += log10(i);
    int digits = int(floor(sum)) + 1;
    cout << digits << endl;
    return 0;
}
示例:输入 10 → 输出 7。说明:10! = 3628800,共 7 位。log₁₀(10!) ≈ 6.5598,floor(6.5598) + 1 = 7。用对数避免大数溢出,是竞赛中的经典技巧。

思路:把 log10(1) 到 log10(n) 逐项累加得到 log10(n!),再向下取整加 1 就是位数。

易错:直接算 n! 会溢出;忘记最后加 1,得到的是位数减一。

C2 编程题

题目:输入直角三角形的两条直角边 a 和 b,计算斜边 c、两个锐角(用度表示),以及三角形的面积和周长。

提示:斜边 c = sqrt(a² + b²) = sqrt(pow(a,2) + pow(b,2));用 atan 求角度,结果转成度:angle = atan(b/a) * 180 / PI。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    const double PI = 3.14159265358979;
    double a, b;
    cin >> a >> b;
    double c = sqrt(a * a + b * b);
    double angleA = atan(b / a) * 180.0 / PI;
    double angleB = 90.0 - angleA;
    cout << "斜边: " << c << endl;
    cout << "角A: " << angleA << "°" << endl;
    cout << "角B: " << angleB << "°" << endl;
    cout << "面积: " << a * b / 2 << endl;
    cout << "周长: " << a + b + c << endl;
    return 0;
}
示例:输入 3 4 → 斜边 5,角A ≈ 53.13°,角B ≈ 36.87°,面积 6,周长 12。说明:atan 返回弧度,转成度要乘 180/PI。直角三角形中两个锐角和为 90°。

思路:先用勾股定理求出斜边,再用反三角函数求角并乘 180/PI 换算成度。

易错:角度忘记乘 180/PI 换算成度;PI 取值精度太低会让结果出现偏差。

C3 编程题

题目:细菌分裂问题。初始有 n 个细菌,每 10 分钟分裂一次(1 个变 2 个)。输入初始数量 n 和目标数量 target,计算至少需要多少分钟才能达到或超过 target 个细菌。

提示:分裂 k 次后数量 = n × 2^k。需要 k 次分裂:n × 2^k >= target → 2^k >= target/n → k >= log₂(target/n)。用 ceil 向上取整。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double n, target;
    cin >> n >> target;
    int k = int(ceil(log(target / n) / log(2)));
    cout << k * 10 << " 分钟" << endl;
    return 0;
}
示例:输入 1 1000 → 输出 100 分钟(10 次分裂,2¹⁰ = 1024 ≥ 1000)。说明:用换底公式 log₂(x) = log(x)/log(2),ceil 向上取整得到最少分裂次数。指数增长非常恐怖,10 次分裂就从 1 变到 1024!

思路:分裂 k 次后数量是 n 乘以 2 的 k 次方,反解出 k = ceil(log2(target/n)),再乘每次的 10 分钟。

易错:用 floor 代替 ceil 会少分裂一次;算出次数后忘记乘 10 分钟。

C4 编程题

题目:输入一个 double 值 x,分别用 floor、round、ceil 三种方式取整,再手动实现一个"银行家舍入"(四舍六入五成双):当小数部分恰好是 0.5 时,向最近的偶数取整。例如 banker(2.5) = 2(2 是偶数,银行家舍入),round(3.5) = 4(4 是偶数)。

提示:银行家舍入:先算 floor(x + 0.5),如果小数部分恰好是 0.5(即 x - floor(x) == 0.5),再判断 floor(x) 是奇数还是偶数。
点击查看参考答案
C++参考代码
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    double x;
    cin >> x;
    int f = int(floor(x));
    int r = int(round(x));
    int c = int(ceil(x));
    int banker;
    double frac = x - f;
    if (frac == 0.5) {
        // 恰好 0.5,向偶数取整
        banker = (f % 2 == 0) ? f : f + 1;
    } else {
        banker = r;  // 不是 0.5,和普通四舍五入一样
    }
    cout << "floor: " << f << "  round: " << r
         << "  ceil: " << c << "  banker: " << banker << endl;
    return 0;
}
示例:输入 2.5 → 输出 floor: 2 round: 3 ceil: 3 banker: 2。说明:银行家舍入(Round Half to Even)是 IEEE 754 浮点标准的默认舍入方式,能减少长期累积的舍入误差。2.5 向最近的偶数 2 取整,3.5 向最近的偶数 4 取整。

思路:先用 floor、round、ceil 分别取整,再对小数部分恰好是 0.5 的情况单独处理成最近的偶数。

易错:用 == 直接判断小数部分是否为 0.5,浮点误差可能判不出来;把「取最近偶数」写成普通四舍五入。