如何在没有循环的二进制数字表示中只计算1位

how to count only 1bits in binary representation of number without loop

本文关键字:表示 计算 1位 二进制数字 循环      更新时间:2023-10-16

假设我有两个数字(最小值和最大值)。`

例如(0和9999999999)

最大值可能如此巨大。现在我还有其他号码。它可以在这些最小和最大数字之间。CCD_ 1。现在我需要做的是得到15(15,30,45 and so on, until it reaches the maximum number)的所有倍数。对于每个数字,我必须计算它们的二进制表示中有多少个1位。for example, 15 has 4(because it has only 4 1bits).

问题是,我需要一个循环中的一个循环来得到结果。第一个循环是得到这个特定数字的所有倍数(在我们的例子中是15),然后对于每个倍数,我需要另一个循环来只计算1比特。我的解决方案花了很多时间。以下是我的操作方法。

unsigned long long int min = 0;
unsigned long long int max = 99999999;
unsigned long long int other_num = 15; 
unsigned long long int count = 0;
unsigned long long int other_num_helper = other_num;
while(true){
if(other_num_helper > max) break;
for(int i=0;i<sizeof(int)*4;i++){
int buff = other_num_helper & 1<<i;
if(buff != 0) count++; //if bit is not 0 and is anything else, then it's 1bits.
}
other_num_helper+=other_num;
}
cout<<count<<endl;

查看0和2^3之间的数字的位模式

000
001
010
011
100
101
110
111

你看到了什么?

每个比特是一个4次。

如果你进行推广,你会发现0和2^n之间的数字总共设置了n*2^(n-1)位。

我相信你可以把这个推理扩展到任意的边界。

下面是我对32位数字的处理方法。

std::uint16_t bitcount(
std::uint32_t n
)
{
register std::uint16_t reg;
reg = n - ((n >> 1) & 033333333333)
- ((n >> 2) & 011111111111);
return ((reg + (reg >> 3)) & 030707070707) % 63;
}

以及程序的支持意见:

把一个3比特的数字想象成4a+2b+c。如果我们把它右移1比特,我们得到了2a+b。把它从原来的数字中减去,得到了2a+c。

例程中的第一个赋值语句计算"reg"。八进制表示中的每个数字只是"n"中相应三位位置中的1的数量。

最后一个return语句将这些八进制数字相加,得出最终答案。关键思想是将相邻的八进制数字对相加在一起,然后计算余数模63。

这是通过将"reg"右移三位,将其添加到"reg"本身,并使用合适的掩码进行"与"运算来实现的。这产生了一个数字,其中六个相邻比特的组(从LSB开始)包含n中这六个位置中的1的数量。这个数字模63产生最终答案。对于64位数字,我们必须添加八进制数字的三元组,并使用模数1023。