【发布时间】:2019-03-01 13:04:42
【问题描述】:
我需要将两个变量合并为一个,如下例所示:
x = 0b110101
y = 0b10011
merged(x,y) -> 0b11010111001merged(y,x) -> 0b10011101011
因此,y 被反转并连接到 x,没有不必要的零(结果的最后一位始终为 1)
换句话说:merged(abcdefg, hijklm) 导致abcdefgmlkjih 其中a 和h 是1
在 C 中最有效的方法是什么
编辑:最有效 = 最快,sizeof(x) = sizeof(y) = 1,CHAR_BIT= 8
EDIT2:由于问题已被搁置,我将在此处发布摘要: 更多限制和更多细节:
目标语言:支持 64 位操作的 C
对于这个确切的问题,最快的方法是 cmets 中建议的 256 元素查找表,它返回高位索引 N 和第二个参数的反转值,所以我们可以将第一个参数向左移动 @987654340 @ 并按位执行 or 与第二个参数的相反值。
如果有人需要为大于 8 位的参数提供良好的性能(查找表不是一个选项),他们可以:
-
使用 de Bruijn 算法查找高位索引。 32 位示例:
uint32_t msbDeBruijn32( uint32_t v ) { static const int MultiplyDeBruijnBitPosition[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; v |= v >> 1; // first round down to one less than a power of 2 v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; return MultiplyDeBruijnBitPosition[( uint32_t )( v * 0x07C4ACDDU ) >> 27]; }
取自这个问题: Find most significant bit (left-most) that is set in a bit array
-
使用此位旋转技巧来反转第二个参数的字节位(一个接一个)
unsigned char b; // reverse this (8-bit) byte b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
取自这里:http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
所以,这个问题现在可以关闭/删除了
【问题讨论】:
-
可移植代码中最棘手的部分是在
y中找到最高 1 位。 -
效率最高?就像使用更少的时间、更少的内存、更少的 CPU、更少的指令,......我猜的 everything 更少?我建议查找数组:)
-
@user3386109 如果您的年龄足以记住 64K 查找表何时大,请举手。 ✋
-
@Barmar 那么就没有必要标记它C++。无论如何,这不是比萨店;我们不会订购我们最喜欢的风格的解决方案,我们会询问我们目前正在编程的语言中的特定问题。
标签: c bit-manipulation