【问题标题】:How to get corresponding value of a bitmask to an integer efficiently?如何有效地将位掩码的对应值转换为整数?
【发布时间】:2019-02-25 16:42:06
【问题描述】:

给定一个整数I和一个位掩码M,从I中得到M的对应值。例如,如果I0x11111 并且M0xff0,则对应的值为0x11

我可以这样做:

  1. IM 之间执行& 操作
  2. 计算右移多少位
  3. 右移

但是这种方式有点慢,尤其是第2步。我想要一个更有效的方法来解决这个问题。

【问题讨论】:

  • 没有比这更好的方法了。您必须始终知道要向右移动多少位。虽然如果你在谈论代码大小,这个操作当然可以只使用一个语句来完成。
  • 慢一点算多慢?多慢才算快?位掩码的可变性是什么 - 是否有一个固定数字可以预先计算右移距离?或者你的位掩码是在某个地方动态生成的,那个地方可以同时生成右移距离吗?

标签: c


【解决方案1】:

我不知道是否有更有效的方法来做到这一点。我一直都和你一样。但是,请考虑通常可以使用单个 CPU 指令来计算右移多少位(您的第二步)。必须使用本能指令来完成,具体取决于您的系统。

在 Windows 上,此操作由 _BitScanForward() 提供,而在 GCC 上,此操作由 __builtin_ctz() 提供。

更多详情请见this answer

例如,您的问题可能的 Windows 实现可能是:

#include <Windows.h>

unsigned int maskandshift(unsigned int m, unsigned int i) {
    unsigned int shift;
    // _BitScanForward returns 0 if the mask is zero.
    // You may prefer the actual number of 0, here:
    if (m == 0)
        shift = sizeof(i) * CHAR_BIT;
    else {
        DWORD trailing_zero;
        _BitScanForward(&trailing_zero, (DWORD)m);
        shift = (unsigned int)trailing_zero;
    }
    return (m & i) >> shift;
}

在发布配置中,此函数被编译为检查零,然后在 x64 机器中仅执行 3 条汇编指令(BSFANDSHR)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    • 2021-07-15
    • 2018-01-15
    • 1970-01-01
    • 2011-10-12
    相关资源
    最近更新 更多