假设我有两个数字(最小和最大)。 `
例如(0和9999999999)
最大值可能是如此之大。现在我还有其他号码。它可以介于最小数和最大数之间。 Let's say 15
。现在我需要做的是获得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)
查看0到2^3
之间的数字的位模式
000
001
010
011
100
101
110
111
您看到什么?
每个位都是四分之一。
如果概括一下,您会发现0到2^n
之间的数字总共设置了n*2^(n-1)
位。
我确信您可以将此推理扩展到任意范围。
答案 1 :(得分: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 + b + c。如果将原始的3位数字右移两位,则得到a,因此再减去一次,我们得到a + b + c,这是原始数字中的位数。
例程中的第一个赋值语句计算“ reg”。八进制表示形式中的每个数字就是“ n”中对应的三个比特位置中1的数目。
最后一个return语句将这些八进制数字加起来以得出最终答案。关键思想是将相邻的八进制数字对加在一起,然后计算剩余的模数63。
这可以通过以下方式完成:将“ reg”右移三位,将其自身添加到“ reg”中,并使用适当的掩码进行“与”运算。这将产生一个数字,其中六个相邻位的组(从LSB开始)包含n中这六个位置中的1。该模为63的数字得出最终答案。对于64位数字,我们必须添加八进制数字的三进制并使用模数1023。