所以我写了这个函数来计算long中的位数,为了我的目的,它包括MSB右边的零并且在它的左边排除零:
int bitCount(unsigned long bits)
{
int len = 64;
unsigned long mask = 0x8000000000000000;
while ((bits & mask) == 0 && len > 0){
mask >>= 1;
--len;
}
return len;
}
就返回正确的答案而言,这个功能对我来说很好,但有没有更好的(更快或其他)方式去做这个?
答案 0 :(得分:0)
如果要计算long
类型中的位数,建议您使用<limits.h>
头文件中的ULONG_MAX
,并使用右移运算符{{1}计算一位的数量。这样您就不必事先知道位数。
像
这样的东西>>
这是有效的,因为右移用零填满。
答案 1 :(得分:0)
任何类型的位数的一般答案是CHAR_BIT*sizeof(type)
。 CHAR_BIT
中定义的<limits.h>
是char
中的(实现定义的)位数。 sizeof(type)
的指定方式会产生用于表示类型的char
个数(即sizeof(char)
为1
)。
答案 2 :(得分:0)
其他人提出的解决方案非常好,可能是最短的写作并且仍然可以理解。另一种直接的方法是这样的
int bitCountLinear(long int n) {
int len = sizeof(long int)*8;
for (int i = 0; i < len; ++i)
if ((1UL<<i) > (unsigned long int)n)
return i;
return len;
}
剩下的可能会有点极端,但我试一试,所以我会分享它。 我怀疑可能有更快的方法可以做到这一点。例如,使用二进制搜索(即使64位的长度非常小)。所以我给你一个快速尝试,并为它带来乐趣。
union long_ing_family {
unsigned long int uli;
long int li;
};
int bitCountLogN(long int num) {
union long_ing_family lif;
lif.li = num;
unsigned long int n = lif.uli;
int res;
int len = sizeof(long int)*8-1;
int max = len;
int min = 0;
if (n == 0) return 0;
do {
res = (min + max) / 2;
if (n < 1UL<<res)
max = res - 1;
else if (n >= (1UL<<(res+1)))
min = res + 1;
else
return res+1;
} while (min < max);
return min+1; // or max+1
}
然后我两个时间来看他们是否有任何有趣的差异......
#include <stdio.h>
#define REPS 10000000
int bitCountLinear(long int n);
int bitCountLogN(long int num);
unsigned long int timestamp_start(void);
unsigned long int timestamp_stop(void);
union long_ing_family;
int main(void) {
long int n;
long int begin, end;
long int begin_Lin, end_Lin;
long int begin_Log, end_Log;
begin_Lin = 0;
end_Lin = 0;
begin_Log = 0;
end_Log = 0;
for (int i = 0; i < REPS; ++i) {
begin_Lin += timestamp_start();
bitCountLinear(i);
end_Lin += timestamp_stop();
}
printf("Linear: %lu\n", (end_Lin-begin_Lin)/REPS);
for (int i = 0; i < REPS; ++i) {
begin_Log += timestamp_start();
bitCountLogN(i);
end_Log += timestamp_stop();
}
printf("Log(n): %lu\n", (end_Log-begin_Log)/REPS);
}
unsigned long int timestamp_start(void) {
unsigned int cycles_low;
unsigned int cycles_high;
asm volatile ("CPUID\n\t"
"RDTSCP\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low)::"%rax", "%rbx", "%rcx", "%rdx");
return ((unsigned long int)cycles_high << 32) | cycles_low;
}
unsigned long int timestamp_stop(void) {
unsigned int cycles_low;
unsigned int cycles_high;
asm volatile ("RDTSCP\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
"CPUID\n\t": "=r" (cycles_high), "=r" (cycles_low)::"%rax", "%rbx", "%rcx", "%rdx");
return ((unsigned long int)cycles_high << 32) | cycles_low;
}
......并不奇怪他们没有。 在我的机器上,我会得到类似的数字 线性:228 记录(n):224 假设存在大量背景噪声,则认为不同。
编辑: 我意识到我只测试了线性方法的最快解决方案,因此将功能输入更改为
bitCountLinear(0xFFFFFFFFFFFFFFFF-i);
和
bitCountLogN(0xFFFFFFFFFFFFFFFF-i);
在我的机器上,我会得到类似的数字 线性:415 记录(n):269 这显然是Log(n)方法的胜利。我没想到会在这里看到差异。