【问题标题】:C quick calculation of next multiple of 4?C快速计算下一个4的倍数?
【发布时间】:2010-01-07 17:18:46
【问题描述】:

将未签名的int 舍入为4 的倍数的快速方法是什么?

4 的倍数有两个最低有效位 0,对吗?所以我可以将它们屏蔽掉,然后执行一个 switch 语句,将 1,2 或 3 添加到给定的uint

这不是一个非常优雅的解决方案..

还有算术汇总:

 myint == 0 ? 0 : ((myint+3)/4)*4

可能有更好的方法,包括一些位操作?

【问题讨论】:

  • 首先,您应该从定义“next”开始(并编写规范:blogs.msdn.com/ericlippert/archive/2009/11/19/…)。
  • 他的代码看起来试图在 4 的边界上对齐?
  • myint 是4 的倍数时,您应该澄清“下一个”的含义。您的算术汇总使myint 保持不变,但在这种情况下,一些回答者已经理解“下一个”的意思是@987654328 @.
  • 例如,"next" 可能意味着 x > n 对于给定 n,或者 x >= n,或者数字 x 使得 |x-n|对于给定的 n 是最小的,或者...
  • 嗯是的 - 我的意思是 - 如果一个 int 不能被 4 整除,它应该向上舍入到 4 的下一个更高倍数

标签: c bit-manipulation


【解决方案1】:
(myint + 3) & ~0x03

加上 3 是为了使下一个 4 的倍数成为前一个 4 的倍数,这是通过模运算产生的,可以通过掩码实现,因为除数是 2 的幂。

【讨论】:

  • 如果 myint 已经是 4 的倍数,则不会给出下一个倍数
  • 确实如此:4 的倍数设置其两个最低位,然后将其屏蔽掉,留下原始位,这也是 OP 代码的工作方式。
  • 迈克尔·布雷斯的批评是正确的。如果 myint 已经是 4 的倍数,则保持不变。 jk 的表达式给出了等于或大于原始值的 4 的最小倍数。这不是我通常理解的“下一个 4 的倍数”的意思。
  • 这就是我对这个问题的意思——我更改了描述以更好地适应我的实际意思:)
  • 如果 myint 为 0,则生成 0。@Stephen:OP 提供了执行他想要的操作的代码,并且“下一个倍数”可以读作四舍五入(根据我的经验,更常见的是),因此迈克尔·布雷的批评不适用于本案。
【解决方案2】:

我假设您要实现的是输入数字的对齐,即如果原始数字已经是 4 的倍数,则不需要更改它。但是,从您的问题中并不清楚。即使原始数字已经是倍数,您也可能想要下一个倍数?请澄清一下。

为了在任意边界 n 上对齐任意非负数 i,您只需要这样做

i = i / n * n;

但这会使它与负无穷大对齐。为了使其与正无穷对齐,请在执行对齐之前添加n - 1

i = (i + n - 1) / n * n;

这对于所有意图和目的来说已经足够好了。在你的情况下,它会是

i = (i + 3) / 4 * 4;

但是,如果您希望从中挤出几个 CPU 时钟,您可以使用 i / 4 * 4 可以替换为有点旋转的 i & ~0x3 的事实,给您

i = (i + 3) & ~0x3;

虽然如果现代编译器能够自己找出后者,我不会感到惊讶。

【讨论】:

  • 来自编辑的评论(即不是我); “i = (i + n - 1) / n * n;(我认为这肯定行不通,你只是在做 +n-1)”和“i = (i + 3) / 4 * 4;(我不要认为这肯定有效,您只是在做 +3)"
  • 我不知道这些cmets是什么意思。我的答案中的表达式使用 integer 除法,它 rounds 其结果。这意味着i = (i + 3) / 4 * 4 显然只是+ 3
【解决方案3】:

如果“4 的下一个倍数”是指大于无符号整数值 myint 的 4 的最小倍数,那么这将起作用:

(myint | 0x03) + 1;

【讨论】:

  • 很好,特别是因为增量可能比添加常量更快。但似乎这不是 OP 想要的。
  • 它将四舍五入到 8。不是最好的解决方案
【解决方案4】:

(myint + 4) & 0xFFFC

【讨论】:

  • 我想这取决于当数字已经被 4 整除时如何定义“下一个”。
  • 这也取决于myint的大小为2字节,如果sizeof myint > 2,则将最高有效字节设置为0。
  • @Alok:是的,但修复起来很简单。
  • 简单的解决方法是使用 ~0x3,它与 int 的大小无关。
  • @Michael:我很迂腐,因为这是一个编程网站。你的答案,以目前的形式,是错误的。没有冒犯的意思(不,我没有对你投反对票)。
【解决方案5】:

如果您希望下一个 4 的倍数严格大于 myint,则此解决方案可以(类似于以前的帖子):

(myint + 4) & ~3u

如果您想要四舍五入到最接近的 4 倍数(如果它 4 的倍数,则保持 myint 不变),这应该可以:

(0 == myint & 0x3) ? myint : ((myint + 4) & ~3u);

【讨论】:

    【解决方案6】:

    myint = (myint + 4) & 0xffffffc

    这是假设你总是向上移动的“下一个 4 的倍数”;即 5 -> 8 和 4 -> 8.

    【讨论】:

      【解决方案7】:

      这是无分支的,通常可配置,易于理解(如果您了解 C 字节字符串),它可以让您避免考虑 myInt 的位大小:

      myInt += "\x00\x03\x02\x01"[myInt & 0x3];
      

      唯一的缺点是可能对堆栈以外的其他地方(静态字符串存储)进行单一内存访问。

      【讨论】:

        猜你喜欢
        • 2010-12-23
        • 2016-01-26
        • 2016-02-21
        • 1970-01-01
        • 1970-01-01
        • 2011-05-12
        • 1970-01-01
        • 2019-01-06
        • 1970-01-01
        相关资源
        最近更新 更多