将位掩码值(1、2、4、8 等)映射到向量索引(1、2、3、4 等)的有效方法
我有一个包含一组值的枚举,这些值可以按位或组合在一起:
enum EventType_e
{
EventType_PING = 1,
EventType_PANG = 2,
EventType_PONG = 4,
EventType_PUNG = 8
};
我预计此枚举将增长到最多包含 15-20 个项目。在收到这些枚举值之一时,我希望能够将其映射到向量,但我不想使用稀疏数组,而是希望将这些值折叠起来。将 1,2,4,8,16,32 映射到 1,2,3,4,5,6 的最佳方法是什么(即在 2^x=1, 2^x=2, 2 中查找“x”) ^x=4、2^x=8 等)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您想要使用二进制对数:
You want to use a binary logarithm:
如果枚举值是 2 的幂,那么我订阅已经建议 log2 的答案(他们比我先一步),但“建议”你使用一些“花哨的”Bit Twiddling Hacks(检查找到整数以 2 为底的对数部分)。
If the enumerated values will be powers of 2 then I subscribe to the answers that already suggest log2 (they beat me to it) but "advising" you to use some "fancy" Bit Twiddling Hacks (check the sections find log base 2 of an integer).
您本质上要求的是:“给定存储在整数 X 中的 2 的幂,找到指数 E 的最有效方法是什么?”
简单的方法是搜索那个重要的指数非零位:
请注意,这将为
X = 1
输出E = 0
- 您可能需要将E
初始化为1
有E = 1
表示X = 1
。What you are essentially asking for is: "Given a power of 2 stored in an integer X, what is the most efficient way to find the exponent E?"
The simple approach would be to search for that significant non-zero bit:
Note that this will output
E = 0
forX = 1
- you may want to initialiseE
to1
to haveE = 1
forX = 1
.大多数现代CPU架构都有操作码来发现数字中最高或最低有效的非零位(例如,x86 上的 BSF 和 BSR)。这些也可作为某些编译器上的内在函数使用,例如 Microsoft 和 Intel 编译器上的
_BitScanForward
和_BitScanReverse
。上面的位扫描无疑是最快的解决方案。对于更便携的解决方案,请向右移动,直到该位从末尾脱落:
请注意,这会返回 0, 1, 2, 3,这比 1, 2, 3, 4 更适合矢量索引。
更复杂但更快的便携解决方案是二元斩波:
Most modern CPU architectures have opcodes to discover the most or least significant non-zero bit in a number (e.g., BSF and BSR on x86). These are also available as intrinsics on some compilers, such as
_BitScanForward
and_BitScanReverse
on Microsoft and Intel compilers.The above bit-scan is hands-down the fastest solution. For a more portable solution, shift right until the bit drops off the end:
Note that this returns 0, 1, 2, 3, which is more appropriate for vector indexing than 1, 2, 3, 4.
A more complex but faster portable solution is a binary chop:
“求 x”的函数称为对数。在本例中为 log2。没有针对整数的标准 C log2 函数,计算是一个小循环。根据您的架构,您的 cpu 可能有一条 asm 指令来获取最高位,其作用相同。
在我看来,更好的解决方案是反过来。
定义类似的东西
(您也可以在此处使用枚举)。
然后在你的事件枚举中创建类似的东西
The function for "finding x" is called logarithm. In this case log2. There is no standard C log2 function for ints, and computing is a small loop. Depending on your architecture your cpu has maybe an asm instruction to get the highest bit, which does the same.
Better solution in my eyes is to it the other way around.
Define something like
(You could also use enum here).
And then make in your event enum something like