关于数学函数和数据类型扩展的详细讲解(从属GESP二级)
本章内容
数学函数使用
数据类型扩展全解
让库函数做繁重算术,让你专注灵感与逻辑 —— 代码如诗,分数自来!
一、数学函数使用
1 📚 函数族全景图
功能 | C 头文件 | C++ 推荐头文件 | 主要原型(最常考) | 等价/重载 & 备注 |
绝对值 |
|
/ |
|
、 |
浮点绝对值 |
|
|
| 也有 |
平方根 |
|
|
|
、 |
取整 (四舍五入) |
|
|
| 同族: |
最大\最小 |
(宏) |
|
|
完整有三参版: |
随机数 |
|
|
/ | C++11 可用 |
万能头 vs 标准头
- •
#include <bits/stdc++.h>
在 OJ / 考试环境可直接用,但记住对应正式头文件,万一机考不支持万能头能立刻拆分。 - • 凡是浮点函数,“返回 double”是核心考点——特别是填空题会用“返回类型”来卡分。
2 🔬 语义+类型陷阱深挖
2.1 abs / fabs / std::abs
输入 | 可能返回 | 潜在坑 |
(-2147483648) | 未定义 → 溢出 | 题目爱考: |
(-3.7) 用 | 3 → 被隐式截断!( | 只能 |
三目运算自己写 | 溢出同上 | 建议优先库函数 |
真题·判断:“abs(-3.2)
的结果是 3.2” → 错(3)
2.2 sqrt
常考点 = 浮点误差 + 非负判定
double r = sqrt(16); // 4.0
bool ok = (sqrt(10)*sqrt(10) == 10); // 可能 false
真题·单选:“若 x
为 double
,表达式 sqrt(x)*sqrt(x)==x
恒为真吗?” → 否,要用 fabs(...)<1e-9
。
2.3 round / floor / ceil / trunc
函数 | 3.2 → | -3.2 → | 易混点 |
| 3 | -3 | “四舍五入到最近整数” |
| 3 | -4 | “向下” ⟹ 不一定绝对值增大 |
| 4 | -3 | “向上” ⟹ 不一定绝对值增大 |
| 3 | -3 | 丢掉小数部分 |
补充:大纲主考 round
,但 2024-12 卷出现“floor
的返回值是 ___?”的填空,一旦见到要能秒答。
2.4 max/min
- • 宏污染:若先
#define max
(某些旧库),std::max
会被替换导致编译错。写题时养成加std::
前缀。 - • 三参:
max({a,b,c})
(C++11);或两层:max(max(a,b),c)
——这个写法经常出现在填空题里考“括号匹配”。
2.5 rand / srand
- 1.
rand()
范围:0 ~ RAND_MAX
(常为 32767) - 2. 均匀映射方案:
-
- •
[0,k-1]
→rand()%k
- •
[1,k]
→rand()%k+1
- •
[l,r]
→rand()%(r-l+1)+l
- •
- 3. 种子只调一次:srand(static_cast<unsigned>(time(nullptr)));
- 4. 概率题常考:生成 1000 次模拟骰子;或判断
(rand()%2)
得到 0/1 概率是否均为 0.5。
3 🔧 真题级“套路”拆解
类型 | 题型原句(缩写) | 考点 | 速答 |
单选 | “以下表达式值为 5 的是?” 选项有 | 四舍五入 | 5 |
判断 | “调用 | 运行结果 | 对;且会 |
填空 | “生成 1–100 随机整数: | 模 ±1 | 100 |
选择 | “以下选项能比较浮点 | 绝对误差 |
|
编程 | “输入 n,输出 1 ~ n 中绝对值 ≤ 2 的整数平方根之和(保留2位)” |
+ |
|
4 🛠 实战模板 & 扩展技巧
4.1 统一随机函数封装
int rng(int l, int r) { // 闭区间 [l,r]return rand() % (r - l + 1) + l;
}
- • 编译器常量折叠考点:如果
l
、r
为字面值,考题会问“此函数返回值个数是 ___ ?”答案=r-l+1
。
4.2 快速近似比较
bool equal(double a,double b,double eps=1e-9){return fabs(a-b)<=eps;
}
- • 真题曾考:“
eps
默认值放在.h
文件里是否可行?” → 可行,只要声明与定义保持一致。
4.3 整数平方判定(≥ 1e9 安全版)
bool isSquare(long long x){long long r = (long long)(sqrt((long double)x)+0.5); // 先转 long double, +0.5 抗误差return r*r==x;
}
- • 填空题爱出
+0.5
的用途:减少浮点误差。
5 📝 “加一级难度”练习
- 1. 随机打乱
读入 n
(< 100) 个整数,要求随机输出其一个全排列。
提示:用 std::shuffle(v.begin(),v.end(),std::default_random_engine(time(0)))
;若局限 rand()
,可写 Fisher-Yates:
- for(int i=n-1;i>0;--i) swap(v[i],v[rng(0,i)]);
- 2. 开根误差
输入整数 k (1≤k≤10^6)
,输出最小 n
使 sqrt(n)
的小数部分≥ 0.999。
提示:
- while(true){ n++; double z=sqrt(n); if(z-floor(z)>=0.999) break; }
- 3. 比赛评分
7 个评委打分(浮点),去掉最高与最低后取平均;要求四舍五入到 1 位小数。
提示: round(sum/5*10)/10
or cout<<fixed<<setprecision(1)
6 ⚠ 容易丢分的 4 件小事
- 1. 忘记
std::
命名空间
-
- • 选择题经常放选项
max(a,b)
、std::max(a,b)
,考哪一个能编译。
- • 选择题经常放选项
- 2. 类型提升陷阱
-
- •
abs(a-b)<=0.1
若a,b
为int
,表达式恒 0/1;要保证它们是double
。
- •
- 3.
rand()
取模偏差(进阶)
-
- • 当
RAND_MAX
不能被(r-l+1)
整除,大数据模拟会产生轻微偏斜。二级通常不深究,但加分题可能问。
- • 当
- 4.
sqrt
输入负数
-
- • 行为未定义,在线判题常直接
nan
;考试机考选择题会给domain error
。
- • 行为未定义,在线判题常直接
🗂️ 二、数据类型扩展全解
1 🌳 数据类型家族速览
类别 | 关键成员 | 关键词/后缀 | 必考点 |
整型 |
、 | 补语: | 字节数、范围、溢出规则 |
字符 |
/ | 字面量前缀: | Unicode 扩展、宽字符 I/O |
浮点 |
、 | 字面量后缀: | 精度、舍入误差、 |
布尔 |
| 常量: | 与整型的隐式转换 |
枚举 |
、 | 位域、作用域限定 | 枚举到整型的提升 |
特殊 |
、 | 空类型、空指针常量 | 只能做指针转换 |
C99 定宽 |
、 | 头文件 | 容易在填空题出现 |
2 🧩 整型版图 —— 字节、范围、陷阱
2.1 统一表格
关键字 | 最小宽度† | 考试机器(64-bit GCC) | 常见范围 (十进制) |
| 8 bit | 1 byte | −128 ~ 127 |
| 8 bit | 1 byte | 0 ~ 255 |
/ | 16 | 2 bytes | −32768 ~ 32767 |
| 16 | 2 bytes | 0 ~ 65535 |
| 16 | 4 bytes | −2 147 483 648 ~ 2 147 483 647 |
| 16 | 4 bytes | 0 ~ 4 294 967 295 |
| 32 | 8 bytes(LLP64*例外) | 约 ±9.22e18 |
| 64 | 8 bytes | 同上 |
| 64 | 8 bytes | 0 ~ 1.84e19 |
2.2 溢出规则
场景 | 行为 | 真题套路 |
有符号整型溢出 | 未定义 (UB) | 判断题:“ |
无符号溢出 | 按 2^n 取模 | 单选:“ |
混合运算提升 | 先提升到 | 填空: |
3 🔬 浮点精度与比较
类型 | 字节 | 有效十进位 | 典型 ε ( |
| 4 | 6 ~ 7 | 1.19e-7 |
| 8 | 15 ~ 16 | 2.22e-16 |
(x86-64) | 16(10) | 18 ~ 19 | 1.08e-19 |
- • 比较模板:
bool d_equal(double a,double b,double eps=1e-9){return std::fabs(a-b)<=eps;
}
- • 真题暗雷
“double s = 0.1+0.2; printf("%.17f",s);
输出不等于 0.300000…”
考点:二进制小数误差;调 setprecision(17)
看到 0.30000000000000004。
4 📝 字面量与后缀
写法 | 推导类型 | 备注 |
|
| 最短类型能装就选 |
/ |
| 真题常让填 |
/ |
|
|
/ |
|
|
(C++14) |
十六进制,撇号可分隔 | 数字可读性 |
|
| 默认双;千万别默认为 float |
/ |
|
|
|
| windows x64 仍 8 bytes |
5 📦 sizeof
、decltype
、auto
int a = 5;
long b = 6;
cout << sizeof(a) << sizeof 'A'; // 4 1 (单引号为 char)
auto c = a + b; // c 推为 long
decltype(a+b) d; // 与 c 同型
填空常问:sizeof(0ULL)
-> 8;sizeof "abc"
-> 4 (含终止 0)。
6 🎨 枚举与 enum class
enum Color { RED, GREEN=5, BLUE }; // 隐式转 int
enum class Dir : unsigned char { N,S,E,W }; // 强作用域 + 自定底层
考点 | 题型 | 速解 |
隐式提升 | “ | 普通 enum |
作用域 | “ | 无流插;需显式强转 |
7 ⚙️ typedef
vs using
typedef unsigned long ull;
using ull2 = unsigned long;
- • 选择题常抛
using
,问两者是否等价 ➟ 等价。 - • 模板别名只能用
using
:template<class T> using vec = std::vector<T>;
8 🚧 真题高频坑位
关键词 | 坑点 | 记忆法 |
默认符号性 |
or | 考卷若问范围,答“依实现,通常 −128~127” |
整数提升 |
? | 先都升至 |
移位超位宽 |
在 32-bit UB | 题目若给 |
布尔加减 |
→ 6 |
|
结构体对齐 | 机考编程: | 末尾对齐到最大成员 |
9 🛠️ 练手 mini-task
- 1. 打印各基本类型字节数:写一行循环
cout<<typeid(T).name()<<...
。 - 2. 安全读取宽字符:输入 UTF-8,存入
std::u32string
,统计码点数。 - 3. 模拟无符号溢出计数器:
uint8_t t=250; for(int i=0;i<10;++i) cout<<(int)(t++);
📈
三、精选选择题(10题)
✅ 1. 【数学函数使用 · 真题】
题目:在 C++ 中,下面哪条语句最适合连续 5 次正确生成 1 到 10 之间的随机整数?
A. rand() % 11
B. rand() % 10
C. rand() % 10 + 1
D. rand() % 9 + 1
答案:C
解析:rand()
产生 0 – RAND_MAX 的伪随机数,先 % 10
得到 0 – 9,再 + 1
即可映射为 1 – 10。
【出自:25 年 3 月题 14】
✅ 2. 【数学函数使用 · 真题】
题目:若 a
、b
均为 float
,要判断它们“几乎相等”(误差 ≤ 0.000001)应选用:
A. (b-a) < 0.000001
B. (b-a) <= 0.000001
C. abs(b-a) <= 0.000001
D. sqrt(b-a) <= 0.000001
答案:C
解析:浮点数可能一大一小,必须取 “距离” abs(b-a)
;误差范围采用 ≤。
【出自:25 年 3 月题 15】
✅ 3. 【数学函数使用 · 真题】
题目:下列 4 个表达式中,结果不是整数 8 的是:
A. abs(-8)
B. min(max(8, 9), 10)
C. int(8.88)
D. sqrt(64)
答案:B
解析:max(8, 9)
得 9,随后 min(9, 10)
仍为 9;其余三个都等于 8。
【出自:24 年 3 月题 5】
✅ 4. 【数学函数使用 · 真题】
题目:下面哪行代码能在 1-100 之间找出所有完全平方数(如 16 是 4²)?
A.int(sqrt(i))*int(sqrt(i)) = i
B.int(sqrt(i)) == sqrt(i)
C.int(sqrt(i))*int(sqrt(i)) == i
D.int(sqrt(i)) = sqrt(i)
答案:C
解析:对i
开平方后再平方,与原数相等即可判定i
为完全平方数;需两侧均为表达式,且用比较运算符==
。
【出自:23 年 12 月题 11】
✅ 5. 【数据类型扩展 · 真题】
题目:若 char a
保存某字符,下列哪一表达式可以判断a
是否为数字字符?
A.'0' <= a && a <= '9'
B.'1' <= a && a <= '0'
C.'0' <= a <= '9'
D.'1' <= a <= '0'
答案:A
解析:字符本质是整数(ASCII),用区间比较最安全;'0'
–'9'
连续。
【出自:23 年 6 月题 12】
✅ 6. 【数据类型扩展 · 真题】
题目:若 char a = 'C';
下面 C++ 语句 cout << (a + 2);
的输出是:
A. E
B. C+2
C. C2
D. 69
答案:D
解析:'C'
的 ASCII 是 67;字符参与算术先提升为 int
,a + 2
是 69,按整数格式输出。
【出自:23 年 6 月题 10】
✅ 7. 【数据类型扩展 · 真题】
题目:a、b、c、d
全为 int
,求它们平均值应写:
A. (a+b+c+d)/4
B. (a+b+c+d)%4
C. (a+b+c+d)/4.0
D. (a+b+c+d)%4.0
答案:C
解析:若除数是整数 4 则仍做整数除法;加上 .0
让表达式晋升为浮点,得到精确均值。
【出自:23 年 3 月题 8】
✅ 8. 【数据类型扩展 · 真题】
题目:C++ 表达式 int(-123.123 / 10)
的值是:
A. -124 B. -123 C. -13 D. -12
答案:D
解析:-123.123 / 10
≈ -12.3123,向 0 截断得到 -12。
【出自:23 年 9 月题 5】
✅ 9. 【数据类型扩展 · 真题】
题目:在 C++ 中,下面哪条语句能直接取得正整数 N
的个位数字?
A. N % 10
B. N / 10
C. N && 10
D. 以上都不行
答案:A
解析:模运算 %
得到除以 10 的余数,即个位。
【出自:24 年 9 月题 7】
✅ 10. 【数据类型扩展 · 真题】
题目:执行 cout << (5 / 2 + 5 % 3);
的输出是:
A. 1 B. 2 C. 4 D. 5
答案:C
解析:5/2
做整除得 2,5%3
得 2,总和 2+2=4。
【出自:24 年 9 月题 5】
三、精选判断题(10题)
✅ 1. 【数学函数使用·真题】
题目:在 C++ 代码中,若 N
为正整数,则表达式 N - N / 10 * 10
与 N % 10
得到的结果始终相同。
答案:对
解析:N / 10
进行整数除法去掉个位后再反推,可得到与取模 % 10
完全相同的余数。
【出自:25 年 3 月判断题】
✅ 2. 【数学函数使用·真题】
题目:对任何正整数 N
,判断式 (sqrt(N) * sqrt(N)) == N
一定返回 true
。
答案:错
解析:sqrt
返回 double
,两次浮点运算会引入误差,比较结果并非总为真。
【出自:25 年 3 月判断题】
✅ 3. 【数据类型·真题】
题目:若 double x = 16.44;
,执行 cout << x / 10;
时输出结果固定为 1
。
答案:错
解析:x / 10
为 1.644
(double
型),不会被截断为整数 1。
【出自:24 年 6 月判断题】
✅ 4. 【数据类型·真题】
题目:执行
int N = 10;
cout << N / 4 << "->" << N % 4 << "->" << N / 4.0;
输出应为 2->2->2.0
。
答案:错
解析:最后一次除数为 4.0
会晋升为浮点运算,结果是 2.5
,因此实际输出 2->2->2.5
。
【出自:24 年 6 月判断题】
✅ 5. 【数据类型·判断】
题目:表达式 ('0' <= ch && ch <= '9')
能正确判断字符 ch
是否为数字字符。
答案:对
解析:字符在算术比较中按 ASCII 值参与运算,数字区间 '0'
–'9'
连续,用区间判断最安全。
【出自:23 年 6 月选择题改编】
✅ 6. 【数据类型】
题目:若 char c = 'C';
,执行 cout << (c + 2);
将输出字符 E
。
答案:错
解析:'C'
的 ASCII 为 67,c + 2
先提升为 int
,结果 69,以整数形式输出而非字符。
【出自:23 年 6 月选择题改编】
✅ 7. 【数据类型】
题目:在 C++ 中,表达式 (a + b + c + d) / 4
能得到四个 int
数的精确平均值(含小数部分)。
答案:错
解析:除数为整数 4
,整体做整数除法,小数部分被截掉;需写 / 4.0
才能保留小数。
【出自:23 年 3 月选择题改编】
✅ 8. 【数据类型】
题目:C++ 表达式 int(-123.123 / 10)
的计算结果为 -12
。
答案:对
解析:-123.123 / 10 ≈ -12.3123
,强转 int
向 0 截断,结果为 -12
。
【出自:23 年 9 月选择题改编】
✅ 9. 【数学函数使用】
题目:rand() % 10 + 1
可以生成的随机整数范围是 1 – 10(含 10)。
答案:对
解析:rand() % 10
得 0 – 9,再 + 1
映射为 1 – 10。
【出自:25 年 3 月选择题改编】
✅ 10. 【数据类型】
题目:在 C++ 代码中,表达式 N % 10
可以用来获取正整数 N
的个位数字。
答案:对
解析:取模 % 10
保留除以 10 后的余数,即个位数。
【出自:25 年 3 月判断题】