奇怪?为什么 floor((n + t - 1) / t) 比 ceil(n / t) 更高效?(因为没有浮点转换带来的性能损耗)

为什么 (n + t - 1) // tceil(n / t) 更高效?

导言

在刷leetcode的时候,发现了用 (n + t - 1) / t替换ceil(n/t)从而带来的性能优化

原理:(因为没有浮点转换带来的性能损耗)

在处理数组分块、分页计算等场景时,我们经常需要计算向上取整的除法。例如,将长度为103的数组分成长度为10的块,需要计算ceil(103/10)=11

常见的实现方式有两种:

  1. 直接向上取整:math.ceil(n / t)
    • math.ceil(103/10)=11
  2. 整数运算模拟:(n + t - 1) // t(这里//表示纯整数除法)
    • (103+10-1)//t=11

虽然结果相同,但后者在多数情况下更高效(因为没有浮点转换带来的性能损耗)。

数学原理(太妙啦啦啦啦啦啦啦啦啦)

偏移量设计

选择t-1作为偏移量的原因:

  1. 当n能被t整除时​(余数r=0):

    • n = k*t
    • (n + t - 1) // t = (k*t + t - 1) // t = k + (t-1)//t = k(正确)
  2. 当n不能被t整除时​(余数r≥1):

    • n = k*t + r
    • (n + t - 1) // t = (k*t + r + t - 1) // t = k + (r + t - 1)//t = k + 1(正确)

示例验证

python 复制代码
# 整除情况
(4 + 2 - 1) // 2 = 5 // 2 = 2  # 等同于ceil(4/2)
# 非整除情况
(5 + 2 - 1) // 2 = 6 // 2 = 3  # 等同于ceil(5/2)

性能分析

ceil(n / t)的问题

大多数语言在实现这个函数的时候,内部都会使用强制浮点运算

  1. 强制浮点运算​:

    • 整数→浮点转换
    • 浮点除法
    • 浮点取整

强制浮点运算会带来性能损耗

(n + t - 1) // t的优势

这里的//在python中表示纯整数除法

python 复制代码
sum = (103+10-1)//10 = 11

在java或者C/C++中只要类型是int,计算除法的时候就会触发纯整数除法

java 复制代码
int sum = (103+10-1)/10 = 11
  1. 纯整数运算​:

    • 直接使用CPU整数除法指令
    • 无类型转换开销

更稳定不受浮点精度限制,需要纯整数运算支持,例如下面的语言

语言特性差异

语言 推荐写法 原因
C/C++/Java (n + t - 1) / t 整数除法直接截断
Python (n + t - 1) // t //避免浮点运算
JavaScript/TS Math.ceil(n / t) JS和TS中的所有除法都是浮点运算,使用Math.ceil可读性优先
高性能场景 (n + t - 1) >> k (t=2^k) 位运算最快

建议

  1. 优先考虑整数运算​:

    • 在支持整数除法的语言中使用(n + t - 1) // t
  2. 可读性与性能平衡​:

    • 在JS/TS等语言中,Math.ceil的可读性更佳
  3. 特殊场景优化​:

    • 当除数为2的幂次时,可用位运算进一步优化
  4. 避免过早优化​:

    • 非性能关键路径可优先考虑代码可读性

总结

(n + t - 1) // t通过巧妙的数学设计,在多数编程语言中实现了:

  • 更高效的纯整数运算
  • 避免浮点转换开销
  • 更好的大数稳定性

6666666666666666666

相关推荐
yuren_xia3 小时前
Spring Boot中保存前端上传的图片
前端·spring boot·后端
普通网友4 小时前
Web前端常用面试题,九年程序人生 工作总结,Web开发必看
前端·程序人生·职场和发展
Humbunklung5 小时前
Rust 控制流
开发语言·算法·rust
站在风口的猪11085 小时前
《前端面试题:CSS对浏览器兼容性》
前端·css·html·css3·html5
鑫鑫向栄6 小时前
[蓝桥杯]取球博弈
数据结构·c++·算法·职场和发展·蓝桥杯·动态规划
JohnYan6 小时前
Bun技术评估 - 04 HTTP Client
javascript·后端·bun
shangjg36 小时前
Kafka 的 ISR 机制深度解析:保障数据可靠性的核心防线
java·后端·kafka
m0_634448896 小时前
从上下文学习和微调看语言模型的泛化:一项对照研究
学习·算法·语言模型
青莳吖7 小时前
使用 SseEmitter 实现 Spring Boot 后端的流式传输和前端的数据接收
前端·spring boot·后端
Once_day7 小时前
代码训练LeetCode(21)跳跃游戏2
算法·leetcode