确定位移量的最优雅方法
Posted
技术标签:
【中文标题】确定位移量的最优雅方法【英文标题】:Most elegant way to determine how much one has been bitshifted 【发布时间】:2021-08-11 11:51:12 【问题描述】:假设我们将 1 位移了某个数字 x;例如,在 c 中:
unsigned char cNum= 1, x= 6;
cNum <<= x;
cNum 将等于 01000000b (0x40)。
简单易懂。但是如果不使用查找表或 while 循环,是否有一个简单的操作可以获取 cNum 并返回 x?
【问题讨论】:
您要做的是计算前导零,或找到第一个位。一些平台有可以做到这一点的指令,而一些语言有使用这些指令的简单方法。您以 C 为例,但并不清楚您是在寻找通用的数学方法,还是特定的语言实现。 我将使用 c 来实现答案,但如果有人要解释使用简单数学找到 x 的优雅方法,那很好。 C 中没有标准的方法可以快速完成。 POSIX 添加了ffs
,GCC 添加了内在函数,一个好的编译器甚至可以检测到手动循环并使用正确的指令对其进行优化。
我已经修改了标题,因为我真的只想要最简单的方法来获取仅设置一个位的位图中的位索引。 log2() 会这样做,但需要一个浮点数;我更喜欢使用整数。
如果您想要标准 C,最好的方法是查看这个 C++ 问题中的答案:***.com/questions/994593/…。
【参考方案1】:
AFAIK,没有“简单”公式可用。
但是,可以计算最高有效(或最低有效)设置位的索引:
a = 000010010, a_left = 3, a_right = 1
b = 001001000, b_left = 5, b_right = 3
班次之差为 2(或 -2)。
然后可以将较小的值移动abs(shift)
来比较a << 2 == b
。 (在某些架构中存在有符号值的移位,它在没有绝对值或检查需要进行移位的方式的情况下工作。)
在 ARM Neon 中有一条用于计算 MSB 位的指令,而在 Intel 中有一条从左右扫描的指令。
【讨论】:
【参考方案2】:log2(cNum)+ 1;将产生 x 其中 cNum != 0,至少在 GNU c 中。
编译器会自动进行强制转换,这可能是不好的形式,但它给了我我需要的东西。
【讨论】:
以上是关于确定位移量的最优雅方法的主要内容,如果未能解决你的问题,请参考以下文章
同一个类中的同名函数 - 有没有一种优雅的方法来确定调用哪个?