惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
Help Net Security
Help Net Security
P
Proofpoint News Feed
J
Java Code Geeks
爱范儿
爱范儿
Last Week in AI
Last Week in AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Full Disclosure
Google DeepMind News
Google DeepMind News
H
Help Net Security
G
Google Developers Blog
Jina AI
Jina AI
Vercel News
Vercel News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
Lohrmann on Cybersecurity
S
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
IT之家
IT之家
Security Archives - TechRepublic
Security Archives - TechRepublic
阮一峰的网络日志
阮一峰的网络日志
N
News and Events Feed by Topic
GbyAI
GbyAI
B
Blog
O
OpenAI News
博客园_首页
Cisco Talos Blog
Cisco Talos Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News: Ask HN
Hacker News: Ask HN
TaoSecurity Blog
TaoSecurity Blog
腾讯CDC
MongoDB | Blog
MongoDB | Blog
M
MIT News - Artificial intelligence
C
Cybersecurity and Infrastructure Security Agency CISA
Cyberwarzone
Cyberwarzone
Webroot Blog
Webroot Blog
Simon Willison's Weblog
Simon Willison's Weblog
Y
Y Combinator Blog
C
Cisco Blogs
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Exploit Database - CXSecurity.com
Security Latest
Security Latest
AI
AI
W
WeLiveSecurity
aimingoo的专栏
aimingoo的专栏
The Register - Security
The Register - Security
Project Zero
Project Zero
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
Blog — PlanetScale
Blog — PlanetScale

博客园 - Sephil

WTL汉化版 Delphi 与 VC 共享接口和对象 DelphiXE泛型不能用类类型做为约束的另类解决方案 百度音乐下载工具 (最后更新: 2012-7-20) 为Delphi应用增加脚本支持 插件框架Extensible Framework for Delphi DirectUI for Delphi VC CListCtrl 第一列列宽自适应 WriteFile写磁盘扇区是87错误的原因 批量更改文件名的批处理文件 替代Windows运行功能的工具FastRun 关于 API 中返回字串的一些问题 BCB/Delphi2007 隐藏任务栏图标 OGA & WGA Crack 所有小工具 迅雷/快车/旋风地址转换器 oracle ora-01033和ora-00600错误 数独游戏 SudokuPuzzle 将文件夹映射为驱动器的工具
[小技巧] 倍数的向上取整和向下取整
Sephil · 2020-02-09 · via 博客园 - Sephil

啥叫倍数的向上取整与向下取整呢?

举个例子,你有一个函数,用来分配一块内存,为了提高运行速度,要对内存大小进行对齐。

function NewMemBlock(const BlockSize, AlignSize: Integer): Pointer;
var
  NewSize: Integer;
begin
  NewSize := ...
  GetMem(Result, NewSize);
end;

假设 BlockSize = 10,AlignSize = 8

所谓向下取整,即 NewSize = 8,是很简单的:

NewSize := BlockSize div AlignSize * AlignSize;
// 10 div 8 * 8 => 1 * 8 => 8

这是因为 div 只会取结果的整数部分而忽略小数部分。

向上取整则需要判断余数,余数不为 0 则需要补齐缺少的部分:

// 0.
NewSize := BlockSize;
if BlockSize mod AlignSize <> 0 then
  Inc(NewSize, AlignSize - BlockSize mod AlignSize);
// 10 mod 8 <> 0 => Inc(NewSize, 8 - 10 mod 8) => Inc(10, 6) => 16

这个代码能达到目的,但是显得很繁琐,我们来简化一下,下面几种方法都可以实现:

// 1.
NewSize := BlockSize + Integer(BlockSize mod AlignSize <> 0) * AlignSize - (BlockSize mod AlignSize);
// 10 + Integer(True) * 8 - (10 mod 8) => 10 + 8 - 2 => 16

// 2.
NewSize := (BlockSize div AlignSize + Integer(BlockSize mod AlignSize <> 0)) * AlignSize;
// (10 div 8 + Integer(True)) * 8 => (1 + 1) * 8 => 16

// 3.
NewSize := Math.Ceil(BlockSize / AlignSize) * AlignSize;
// Math.Ceil(1.25) * 8 => 2 * 8 => 16

代码简化了不少,但是方法 1、2 还是有点长,方法 3 用到了浮点数运算,你懂的。

有没有更简单的办法呢?当然有!一般人我不告诉他~~~请看终级代码:

NewSize := (BlockSize + AlignSize - 1) div AlignSize * AlignSize;
// (10 + 8 - 1) div 8 * 8 => 17 div 8 * 8 => 2 * 8 => 16

这个方法不仅代码简洁,而且执行效率是最高的,比方法 0、1、2 快 1 倍,比方法 3 快 20 倍左右。

至于原理,大家自己去理解一下代码吧~