找到64位数的位置

时间:2013-09-18 15:23:55

标签: c

我正在尝试在64位数字中找到两个1的位置。在这种情况下,那些位于第0和第63位置。这里的代码返回0和32,这只是对齐的一半。为什么这不起作用?

#include<stdio.h>
void main()
{
unsigned long long number=576460752303423489;
int i;
for (i=0; i<64; i++)
    {
    if ((number & (1 << i))==1)
        {
        printf("%d  ",i);

        }   
    }
}

6 个答案:

答案 0 :(得分:24)

行上有两个错误

if ((number & (1 << i))==1)

应阅读

if (number & (1ull << i))

1更改为1ull意味着左移是在类型unsigned long long而不是int的值上完成的,因此位掩码实际上可以到达位置32到63.将比较删除为1是因为number & mask(其中mask只有一位设置)的结果是mask0mask当我为0时,它只等于1。

但是,当我进行更改时,我的输出是0 59,这仍然不是您所期望的。剩下的问题是576460752303423489(十进制)= 0800 0000 0000 0001(十六进制)。 0 59是该数字的正确输出。您想要的号码是9223372036854775809(十进制)= 8000 0000 0000 0001(十六进制)。

顺便说一下,main需要返回int,而不是void,并且需要一个明确的return 0;作为其最后一个操作(除非您正在做一些更复杂的事情返回码)。是的,C99让你省略。无论如何要这样做。

答案 1 :(得分:6)

因为(1 << i)是您正在编译并运行的平台上的32位int值。然后,使用&值对number操作进行符号扩展为64位,从而将位31复制到位32到63中。

此外,您正在将&的结果与1进行比较,这是不正确的。如果该位置位,它将不为0,但不会为1.

将32位int移位32是未定义的。

此外,您的输入数字不正确。设置的位位于0和59位(如果您希望从1开始计数,则为1和60)。

修复是使用(1ull&lt;&lt;&lt; i),或以其他方式右移原始值并将&改为1(而不是左移1)。当然,如果你用原始值左移1和&,结果将不是1(除了第0位),所以你需要比较!= 0而不是{{ 1}}。

答案 2 :(得分:4)

#include<stdio.h>
int main()
{
    unsigned long long number = 576460752303423489;
    int i;
    for (i=0; i<64; i++)
    {
        if ((number & (1ULL << i)))   //here
        {
            printf("%d  ",i);    
        }   
    }
}

首先是使用1ULL来表示unsigned long long常量。第二个是在if语句中,你的意思是不与1进行比较,这对于最右边的位只会是真的。

输出:0 59

这是正确的,因为576460752303423489等于0x800000000000001

答案 3 :(得分:1)

通过采用将>>运算符应用于变量而不是文字的方法,本来可以避免这个问题:

if ((variable >> other_variable) & 1)
   ...

答案 4 :(得分:0)

我知道这个问题有一些时间和多个正确的答案,而我应该是一个评论,但它有点太长了。我建议你在宏中封装位检查逻辑,不要直接使用64号,而是计算它。看看here是否有相当全面的位操作黑客来源。

#include<stdio.h>
#include<limits.h>

#define CHECK_BIT(var,pos) ((var) & (1ULL<<(pos)))

int main(void)
{
    unsigned long long number=576460752303423489;
    int pos=sizeof(unsigned long long)*CHAR_BIT-1;    
    while((pos--)>=0) {
        if(CHECK_BIT(number,pos))
            printf("%d ",pos);
    }
    return(0);
}

答案 5 :(得分:0)

不是诉诸于位操作,而是可以使用编译器工具以最有效的方式执行位分析任务(在许多情况下仅使用单个CPU指令)。

例如,gcc和clang提供了那些方便的例程:

__builtin_popcountll() - number of bits set in the 64b value
__builtin_clzll() - number of leading zeroes in the 64b value
__builtin_ctzll() - number of trailing zeroes in the 64b value
__builtin_ffsll() - bit index of least significant set bit in the 64b value

其他编译器也有类似的机制。