在C ++中,找出存储给定int需要多少位的最快方法是什么?
我可以尝试将数字除以2次,但划分相当慢。有什么快捷方式吗?
编辑:非常感谢答案的人。当我说一个int我的帖子,我的意思是任何4字节int。例如,如果我存储30665,我希望得到15位。
答案 0 :(得分:4)
在C ++ 20中,您只需要使用std::bit_width()
或等同版本
return std::numeric_limits<T>::digits - std::countl_zero(x);
如果您使用的是较旧的C ++标准,请使用boost::multiprecision::msb()
,它会自动映射到当前编译器的适当内在函数,例如__builtin_clz()
或_BitScanReverse()
...
return boost::multiprecision::msb(x);
答案 1 :(得分:3)
您可以逐步将值分解为一半,以便更快地缩小范围。
int bits_needed(uint32_t value)
{
int bits = 0;
if (value >= 0x10000)
{
bits += 16;
value >>= 16;
}
if (value >= 0x100)
{
bits += 8;
value >>= 8;
}
if (value >= 0x10)
{
bits += 4;
value >>= 4;
}
if (value >= 0x4)
{
bits += 2;
value >>= 2;
}
if (value >= 0x2)
{
bits += 1;
value >>= 1;
}
return bits + value;
}
查看实际操作:http://ideone.com/1iH7hG
编辑抱歉,原始版本需要一个额外的期限。现在已经修好了。
编辑2 按照评论中的建议以循环形式。
int bits_needed(uint32_t value)
{
int bits = 0;
for (int bit_test = 16; bit_test > 0; bit_test >>= 1)
{
if (value >> bit_test != 0)
{
bits += bit_test;
value >>= bit_test;
}
}
return bits + value;
}
此算法为0
的输入返回0
,这意味着您根本不需要任何位来编码0
的值。如果您更愿意返回1
,只需将返回值更改为bits + 1
。
答案 2 :(得分:2)
使用比移动“更快”的算法无法执行此操作。
但您可以使用以下算法(包括<cmath>
):
int bits_n(int x) {
return (x != 0)
? std::ceil(std::log(x) / std::log(2))
: 1;
}
对于大多数应用来说可能足够快。
在基数2中执行对数需要std::log(x) / std::log(2)
(因为C和C ++ does not have a function的标准库都可以执行它。)
here你可以找到一个实例。
答案 3 :(得分:2)
查看着名的Bit Twiddling Hacks page,特别是counting bits上的部分。
供参考,这是Brian Kernighan的方法计算设置的位数:
unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
答案 4 :(得分:2)
对于非零无符号整数类型,您可以使用gcc / clang以下之一
sizeof(unsigned) - __builtin_clz(x)
sizeof(unsigned long) - __builtin_clzl(x)
sizeof(unsigned long long) - __builtin_clzll(x)
对于MSVC ++上的32位和64位整数,您可以定义变量index
来存储
_BitScanReverse(&index, x)
_BitScanReverse64(&index, x)
如果您的计算机支持,那些编译器包装器将委托给硬件指令,否则就会委托一些优化的bit-twiddling算法。您可以使用一些#ifdef
来编写自己的半平台独立包装器。
Matthew Fioravante有一个相关的stdcxx-bitops GitHub repo作为floated to the std-proposals
邮件列表,作为为C ++添加constexpr
按位运算库的初步建议。如果标准化,那么会有类似std::clz()
功能模板的功能,可以满足您的需求。
答案 5 :(得分:1)
让我们重新解释这个问题(无论如何对于无符号整数):我的整数的msb是否会下降?
(只是确定你知道为什么)
让我们在十进制中考虑这一点。存储号码需要多少位数?如果我写出了号码(因为计算机将用于任何号码),我所要做的就是计算数字,并报告最大数字的位置。
现在人们不会想二进制,所以你必须在十进制数字和二进制数字之间进行转换......除了计算机会在解析中为你做这些。函数的输入将是一个二进制数,所以你要做的就是找到msb的位置。
获得无符号整数的MSB的最快方法(不幸的是)不是超级便携式的。
What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C?
进入寻找MSB的所有方法。长话短说,虽然C ++可能不会直接为你提供一个钩子,但大多数编译器都将它作为汇编命令内置。所以这将是最快的方式。
答案 6 :(得分:0)
可能最快的方式是使用预先填充的查找表。
const size_t bitsMap [] =
{
0, // value 0 (0)
1, // value 1 (1)
2, // value 2 (10)
2, // value 3 (11)
3, // value 4 (100)
// ...
};
您也可以使用数学方法(例如vector
)在启动时计算此数组(或ceil(log2(n))
或类似数据)。
您现在有一个数字n
,您想知道需要多少位来表示。您只需使用n
索引数组 - 存储的值就是位数。
int main()
{
for (int i = 0; i < 256; ++i)
{
const size_t bits = bitsMap [i];
cout << "The number " << i << " would take " << bits << " to represent."
}
}
立即索引数组。我不知道你怎么会比这更快。
答案 7 :(得分:0)
int num = number;
int count_bit =0;
while (num) {
num = num>>1;
count++;
}
std::cout << num << " needs " << count << " bits" << std::endl;
答案 8 :(得分:0)
首先初始化位= 0。然后循环,直到比特的平方等于数字。
void bits(int x)
{
int bit = 1;
while(pow(2,bit) < x)
{
bit++;
}
printf("%d",bit);
}
另一种方法:
int bit = static_cast<int>(log2(x));