[小技巧] 倍数的向上取整和向下取整

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

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

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 倍左右。

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

原文地址:https://www.cnblogs.com/sephil/p/12287889.html

时间: 2024-10-09 18:23:36

[小技巧] 倍数的向上取整和向下取整的相关文章

js 向上取整、向下取整、四舍五入

js 向上取整.向下取整.四舍五入 CreateTime--2018年4月14日11:31:21 Author:Marydon // 1.只保留整数部分(丢弃小数部分) parseInt(5.1234);// 5 // 2.向下取整(<= 该数值的最大整数)和parseInt()一样 Math.floor(5.1234);// 5 // 3.向上取整(有小数,整数就+1) Math.ceil(5.1234); // 4.四舍五入(小数部分) Math.round(5.1234);// 5 Mat

关于erlang的向上取整和向下取整

在erlang的API中,erlang:trunc/1 是就近取整,erlang:round/1是四舍五入的, 整理下:对于正数的向上和向下取整, 1 %% 向上取整 2 ceil(N) -> 3 T = trunc(N), 4 case N == T of 5 true -> T; 6 false -> 1 + T 7 end. 1 %% 向下取整 2 floor(X) -> 3 T = trunc(X), 4 case (X < T) of 5 true -> T

Python 之 向上取整、向下取整以及四舍五入

python 向上取整ceil 向下取整floor 四舍五入round,相面给出源码示例. import math #向上取整 print "math.ceil---" print "math.ceil(2.3) => ", math.ceil(2.3) print "math.ceil(2.6) => ", math.ceil(2.6) #向下取整 print "\nmath.floor---" print &q

SQL 向上取整、向下取整、四舍五入取整的实例!round、rounddown、roundup

sql server ==================================================== [四舍五入取整截取] select round(54.56,0) ==================================================== [向下取整截取] SELECT FLOOR(54.56) ==================================================== [向上取整截取] SELECT CE

python 向上取整ceil 向下取整floor 四舍五入round

#encoding:utf-8import math #向上取整print "math.ceil---"print "math.ceil(2.3) => ", math.ceil(2.3)print "math.ceil(2.6) => ", math.ceil(2.6) #向下取整print "\nmath.floor---"print "math.floor(2.3) => ", ma

取整,向上取整,向下取整

取整 符号:[ ]  范围   [x]  =  {y ∈ N | y < = x && y > x - 1} 向下取整 符号:?? (floor)floor为地板 横线就在下面   范围 同取整 向上取整 符号:?? (ceiling) ceiling为天花板 横线就在上面 范围 ?x? = {y ∈ N | y > = x && y < x+1} 百度半天都难找到符号 自制百科 随时查阅

Objective-C浮点数转化整数(向上取整、向下取整)

Objective-C拓展了C,自然很多用法是和C一致的.比如浮点数转化成整数,就有以下四种情况. 1.简单粗暴,直接转化 float f = 1.5; int a; a = (int)f; NSLog("a = %d",a); 输出结果是1.(int)是强制类型转化,丢弃浮点数的小数部分. 2.高斯函数,向下取整 float f = 1.6; int a; a = floor(f); NSLog("a = %d",a); 输出结果是1.floor()方法是向下取整

Sql Server 里的向上取整、向下取整、四舍五入取整

==================================================== [四舍五入取整截取] select round(54.56,0) ==================================================== [向下取整截取] SELECT FLOOR(54.56) ==================================================== [向上取整截取] SELECT   CEILING(13.

Sql Server 里的向上取整、向下取整、四舍五入取整的实例!

http://blog.csdn.net/dxnn520/article/details/8454132 ==================================================== [四舍五入取整截取] select round(54.56,0) ==================================================== [向下取整截取] SELECT FLOOR(54.56) =============================