考虑这个程序
#include <iostream>
#include <bitset>
#include <cstdint>
#include <cstdlib>
typedef uint8_t Tnum;
template <typename T>
void printBits(T a)
{
std::cout << std::bitset<(sizeof(a) * 8)>(a).to_string() << '\n';
}
int main()
{
printBits(Tnum(15));
printBits(Tnum(17));
return EXIT_SUCCESS;
}
打印
00001111
00010001
现在考虑前一个输出中的这两个人
00001111
^
00010001
^
我想知道,给定一个有符号或无符号整数类型,并给出该类型实例的值,我可以在模式中获取该前导1
的位置,从0
我期望的结果是第一行3
,第二行4
。我所接受的职位总数也是可以接受的,例如第一行为4
,第二行为5
。
我目前没有Hacker's Delight或类似的文字,我找不到任何快速的小辫子。
This有点像它但它容易出错,它永远不会通过转换测试或一组关于转换的警告标志,至少在我的情况下如此。此外,它可能是一个非最佳选择。
请不要查找表,我愿意接受任何不会导致转换问题且不使用LUT的内容。对于C89 / 99和C ++ 11。
答案 0 :(得分:4)
如果这是X86并且你可以使用汇编,那么就是位扫描反向指令。根据编译器的不同,可能存在固有的内容。
答案 1 :(得分:2)
为什么您无法获得黑客的喜悦?代理限制?
以下是http://www.hackersdelight.org/hdcodetxt/nlz.c.txt
的解决方案int nlz1(unsigned x) {
int n;
if (x == 0) return(32);
n = 0;
if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
if (x <= 0x7FFFFFFF) {n = n + 1;}
return n;
}
答案 2 :(得分:2)
正如其他人所说,x86-64处理器具有最高有效位(MSB)指令,可以使用内联汇编或编译器指令( intrinsics )通过编译器访问。 Microsoft C编译器具有32位的 _BitScanReverse 指令。
可以在此处找到如何为gcc编译器插入内联汇编代码的示例:https://www.biicode.com/pablodev/pablodev/bitscan/master/25/bitboard.h
如果您对此类解决方案不感兴趣,使用de Bruijn魔术数字在表格大小和速度之间做出妥协的O(log(N))解决方案是:
uint32_t v;
int r;
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;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
基本上,第一个将输入数字转换为小于2的幂的一个,然后de Bruijn乘法和查找完成剩下的工作。当已知输入数是2的幂时(虽然幻数不同),不需要移位。所有信息均可用here。
答案 3 :(得分:1)
如果您正在使用visual studio,则可以使用BitScanRevers内在函数。