📌 基本概念
#include <cmath> // 必须包含的头文件
double ceil(double x); // 向上取整
float ceilf(float x); // float版本
long double ceill(long double x); // long double版本
- 功能:返回不小于x的最小整数值(向+∞方向取整)
- 时间复杂度:O(1)
🚀 典型用法
1. 基本取整
cout << ceil(3.2); // 输出4
cout << ceil(-2.7); // 输出-2(注意负数方向)
2. 配合除法使用(竞赛高频)
// 计算a/b的上取整(经典技巧)
int a = 5, b = 2;
int res = (a + b - 1) / b; // 方法1:整数运算
int res = ceil(a / (double)b); // 方法2:转为浮点
3. 分数处理
// 计算⌈x/y⌉ * z
double ans = ceil(x / y) * z;
🔧 特殊技巧
1. 避免浮点误差
// 错误示例(浮点精度问题)
double d = 0.1 + 0.1 + 0.1; // 实际可能是0.30000000000000004
cout << ceil(d * 100); // 可能输出31
// 解决方案:加微小修正值
const double EPS = 1e-10;
cout << ceil(d * 100 - EPS);
2. 自定义ceil函数(纯整数版)
// 避免浮点运算的ceil实现
int int_ceil(int a, int b) {
return (a + b - 1) / b;
}
// 示例:⌈17/5⌉ = 4
cout << int_ceil(17, 5);
3. 模板化实现
template<typename T>
T safe_ceil(T x) {
T res = ceil(x);
if (abs(res - x) < 1e-9) res = round(x); // 处理x.999999情况
return res;
}
⚠️ 常见坑点
-
整数除法陷阱
int a = 5, b = 2; cout << ceil(a / b); // 输出2!因为先做了整数除法 cout << ceil(a / (double)b); // 正确:3.0
-
负数方向混淆
cout << ceil(-1.5); // 输出-1(不是-2!)
-
浮点精度问题
cout << ceil(0.1 + 0.2); // 可能输出1(实际应为0)
🏆 竞赛应用场景
1. 分页计算
// 计算n个元素每页显示k个需要多少页
int pages = ceil(n / (double)k);
2. 内存对齐
// 计算需要分配的块数(每块BLOCK_SIZE)
int blocks = ceil(total_size / (double)BLOCK_SIZE);
3. 几何问题
// 计算覆盖区域需要的瓷砖数量
int tiles = ceil(length / tile_size) * ceil(width / tile_size);
💡 性能对比
方法 | 精度 | 速度 | 适用场景 |
---|---|---|---|
ceil() | 高 | 慢 | 需要精确浮点结果 |
(a+b-1)/b | 低 | 快 | 纯整数运算 |
int(x + 0.999) | 中 | 中 | 快速近似 |
📌 竞赛建议:优先使用整数运算实现ceil,仅在必须处理浮点时使用标准库函数
// 推荐模板
#define CEIL(a, b) ((a) + (b) - 1) / (b) // 仅适用于正整数