zoukankan      html  css  js  c++  java
  • [小技巧] 倍数的向上取整和向下取整

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

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

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

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

  • 相关阅读:
    AcWing 37. 树的子结构
    AcWing 30. 正则表达式匹配 (剑指OFFER leetcode 10)
    Leetcode 514 自由之路
    AcWing 28. 在O(1)时间删除链表结点
    solrCloud+tomcat+zookeeper配置
    ZooKeeper原理及配置
    ZooKeeper原理及配置
    ZooKeeper原理及配置
    SolrCloud Hello Word
    SolrCloud Hello Word
  • 原文地址:https://www.cnblogs.com/sephil/p/12287889.html
Copyright © 2011-2022 走看看