当前位置: 首页 > news >正文

C++---向上取整

1. 什么是向上取整(Ceiling)

向上取整(Ceiling)是数学中的一个基本概念,表示取大于或等于某个数的最小整数
数学符号是:⌈x⌉\lceil x \rceilx

例子:

  • ⌈2.3⌉=3\lceil 2.3 \rceil = 32.3=3
  • ⌈2.0⌉=2\lceil 2.0 \rceil = 22.0=2
  • ⌈−2.3⌉=−2\lceil -2.3 \rceil = -22.3=2 (注意不是 -3,因为 -2 比 -2.3 大)
  • ⌈−2.0⌉=−2\lceil -2.0 \rceil = -22.0=2

对比:

  • 向下取整(floor):取小于或等于 x 的最大整数
  • 四舍五入(round):根据小数部分决定向上或向下取整

2. C++ 中的除法默认是“向零截断”

在 C++ 中,两个整数相除 / 会执行向零截断(truncate towards zero):

  • 正数:等价于向下取整
  • 负数:等价于向上取整
cout << 7 / 3 << endl;   // 2(7/3=2.333,向零截断)
cout << -7 / 3 << endl;  // -2(不是 -3)

这意味着:

  • 直接用 / 不能直接得到数学上的向上取整结果
  • 需要额外处理才能实现真正的向上取整

3. 实现向上取整的三种主流方法

3.1 使用 <cmath> 中的 std::ceil

C++ 标准库提供了 ceil 函数,定义在 <cmath> 中:

#include <iostream>
#include <cmath>
using namespace std;int main() {double x = 7.0 / 3.0;cout << ceil(x) << endl; // 3double y = -7.0 / 3.0;cout << ceil(y) << endl; // -2
}

特点

  • 支持浮点数,能正确处理负数
  • 缺点:需要先转换成浮点类型,否则整数除法已经截断
  • 有精度误差风险:ceil(8.999999999) 可能得到 8 而不是 9

3.2 整数公式法(适用于正数)

公式:⌈ab⌉=a+b−1b(a,b>0)\lceil \frac{a}{b} \rceil = \frac{a + b - 1}{b} \quad (a, b > 0)ba=ba+b1(a,b>0)

原理

  • 如果 a 能被 b 整除,那么 a + b - 1 除以 b 仍是 a / b
  • 如果不能整除,a + b - 1 会把分子推到下一个能整除的区间

例子:

int a = 7, b = 3;
cout << (a + b - 1) / b << endl; // (7+3-1)/3 = 9/3 = 3 ✅int a2 = 6, b2 = 3;
cout << (a2 + b2 - 1) / b2 << endl; // (6+3-1)/3 = 8/3 = 2 ✅

适用范围

  • a、b 均为正数
  • 对于负数,需要额外调整

3.3 位运算优化法(b 是 2 的幂)

如果 b 是 2 的幂,可以用位运算代替除法,效率更高:
⌈a2k⌉=(a+(1<<k)−1)>>k\lceil \frac{a}{2^k} \rceil = (a + (1 << k) - 1) >> k2ka=(a+(1<<k)1)>>k

例子:

int a = 17, k = 3; // b = 8
int ceil_div = (a + (1 << k) - 1) >> k;
// (17 + 8 - 1) >> 3 = 24 >> 3 = 3 ✅

原理

  • (1 << k) - 1 生成 k 个 1 的掩码
  • 加法后右移 k 位相当于整除 2^k

4. 边界情况处理

4.1 a 或 b 为 0

  • 如果 b = 0:无意义(除零错误)
  • 如果 a = 0:向上取整结果为 0

4.2 负数处理

通用安全公式(支持负数):

int ceil_div(int a, int b) {if (b == 0) throw runtime_error("Division by zero");if ((a > 0 && b > 0) || (a < 0 && b < 0)) {// 同号:用 (a + b - 1) / breturn (a + b - 1) / b;} else {// 异号:直接除(向零截断等价于向上取整)return a / b;}
}

5. 性能对比

方法优点缺点适用场景
std::ceil简单,支持负数浮点精度风险不要求极致性能
(a + b - 1) / b整数运算,无精度问题仅适用于正数算法竞赛、正数场景
位运算速度快仅适用于 b 是 2 的幂内存对齐、性能敏感

6. 实战应用场景

6.1 分页计算

int total_items = 100;
int page_size = 10;
int pages = (total_items + page_size - 1) / page_size; // 10 页

6.2 数组分块

int n = 17;
int block_size = 5;
int blocks = (n + block_size - 1) / block_size; // 4 块

6.3 二分查找中的边界计算

LeetCode 2300:

long long t = (success + i - 1) / i - 1;

这里 (success + i - 1) / i 就是对 success / i 向上取整。


7. 完整代码示例

#include <iostream>
#include <cmath>
#include <stdexcept>
using namespace std;// 通用向上取整函数(支持负数)
int ceil_div(int a, int b) {if (b == 0) throw runtime_error("Division by zero");if ((a > 0 && b > 0) || (a < 0 && b < 0)) {return (a + b - 1) / b;} else {return a / b;}
}// 位运算优化版(b 是 2 的幂)
int ceil_pow2(int a, int k) {return (a + (1 << k) - 1) >> k;
}int main() {// 测试正数cout << ceil_div(7, 3) << endl;    // 3cout << ceil_div(6, 3) << endl;    // 2// 测试负数cout << ceil_div(-7, 3) << endl;   // -2cout << ceil_div(7, -3) << endl;   // -2cout << ceil_div(-7, -3) << endl;  // 3// 测试位运算版本cout << ceil_pow2(17, 3) << endl;  // 3 (17/8=2.125)// 测试标准库函数cout << ceil(7.0 / 3.0) << endl;   // 3cout << ceil(-7.0 / 3.0) << endl;  // -2return 0;
}

8. 总结与建议

  1. 正数场景

    • (a + b - 1) / b 最安全高效
    • 如果 b 是 2 的幂,用位运算 (a + (1 << k) - 1) >> k 更快
  2. 负数场景

    • 用通用公式 ceil_div(a, b)
    • 或直接用 std::ceil((double)a / b)
  3. 性能敏感场景

    • 优先考虑位运算(如果适用)
    • 否则用整数公式法
  4. 精度敏感场景

    • 避免直接用浮点数计算,优先整数公式

生活本来就很精彩。只不过有人没发现自己是作者,没发现他们可以按自己的想法创作。 —约翰·史特列奇

http://www.dtcms.com/a/486951.html

相关文章:

  • 多字节串口收发IP设计(五)串口模块增加数据位停止位动态配置功能(含源码)
  • 上海网站建设专业公司排名百度搜索app
  • Java 设计模式—— 责任链模式:从原理到 SpringBoot 最优实现
  • Linux中快速部署Minio(基础TLS配置)
  • 大型小说网站开发语言望野博物馆
  • 做早餐烧菜有什么网站零基础搭建网站
  • SAP PCE生产订单组件不能更改物料编码和工厂
  • Aosp14系统壁纸的启动和加载流程
  • 电压源和电流源学习理解
  • 刘洋洋《魔法派对Magic Party》童话重启,温柔守护每颗童心
  • 东莞长安网站设计搞网站开发的程序员属于哪一类
  • 运维领域核心概念的专有名词解释-详解
  • 【AIGC】语音识别ASR:火山引擎大模型技术实践
  • 如何在AutoCAD中加载大型影像文件?
  • 爬虫调试技巧:如何用浏览器开发者工具找接口?
  • Linux 页缓存(Page Cache)与回写(Writeback)机制详解
  • 【NI测试方案】基于ARM+FPGA的整车仿真与电池标定
  • JavaScript将url转为blob和file,三种方法
  • 电商营销型网站建设中国菲律宾关系现状
  • 英文网站建设 飞沐wordpress公众号文章分类
  • 怎么做qq靓号网站岳阳网站设计公司
  • Unity 通过Texture生成的Sprite存在边缘黑线问题 Image黑边问题
  • 计算机方向如何才能更好的找到工作?(成长心得)
  • 大连市城市建设投资集团网站网站怎么做文件上传
  • 织梦网站转跳手机站盐城网盐城网站建设站建设
  • Spring AOP 中@annotation的两种写法详解
  • Linux设备模型
  • Linux fg命令使用教程
  • 微博爬虫流程解析——session的使用
  • 企业网站建设的核心是专业手机建站公司