在C中连续计数1

时间:2012-09-26 15:44:40

标签: c bitwise-operators

  

可能重复:
  Finding consecutive bit string of 1 or 0

是否可以从左数开始计算整数中的连续1? 所以:从最高位开始的连续设置位的总数。

仅使用:

! ~ & ^ | + << >>

-1 = 0xFFFFFFFF将返回32

0xFFF0F0F0将返回12(FFF = 111111111111)

不幸的是没有循环。

可以假设机器:

  1. 使用2s补码,32位整数表示。

  2. 以算术方式执行右移。

  3. 将整数移位更多时,行为不可预测  比单词大小。

  4. 我被禁止:

    1. 使用任何控制结构,例如if,do,while,for,switch等。

    2. 定义或使用任何宏。

    3. 在此文件中定义任何其他功能。

    4. 调用任何函数。

    5. 使用任何其他操作,例如&amp;&amp;,||, - 或?:

    6. 使用任何形式的铸造。

    7. 使用除int之外的任何数据类型。这意味着你  不能使用数组,结构或联合。

    8. 我看过了 Finding consecutive bit string of 1 or 0 它使用循环,我不能使用。我甚至不知道从哪里开始。

      (是的,这是一项任务,但我只是要求那些熟练的人帮忙。我已经做了很多我需要做的事情,但是这个不会起作用。)< / p>

      (对于那些仅仅因为它是为了学校而贬低的人: 常问问题: 1一个特定的编程问题,检查 2但是,如果你的动机是“我希望别人向我解释______”,那么你可能就好了。)

5 个答案:

答案 0 :(得分:2)

你在这里。函数参数可以是有符号或无符号的。 alg独立于签名。

int leftmost_ones(int x)
{
    x = ~x;
    x = x | x >> 1 | x >> 2 | x >> 3 | x >> 4 | x >> 5 | x >> 6 | x >> 7 | 
        x >> 8 | x >> 9 | x >> 10 | x >> 11 | x >> 12 | x >> 13 | x >> 14 | 
        x >> 15 | x >> 16 | x >> 17 | x >> 18 | x >> 19 | x >> 20 | x >> 21 | 
        x >> 22 | x >> 23 | x >> 24 | x >> 25 | x >> 26 | x >> 27 | x >> 28 | 
        x >> 29 | x >> 30 | x >> 31;
    x = ~x;
    return (x & 1) + (x >> 1 & 1) + (x >> 2 & 1) + (x >> 3 & 1) + (x >> 4 & 1) + 
        (x >> 5 & 1) + (x >> 6 & 1) + (x >> 7 & 1) + (x >> 8 & 1) + (x >> 9 & 1) + 
        (x >> 10 & 1) + (x >> 11 & 1) + (x >> 12 & 1) + (x >> 13 & 1) + (x >> 14 & 1) +
        (x >> 15 & 1) + (x >> 16 & 1) + (x >> 17 & 1) + (x >> 18 & 1) + (x >> 19 & 1) +
        (x >> 20 & 1) + (x >> 21 & 1) + (x >> 22 & 1) + (x >> 23 & 1) + (x >> 24 & 1) +
        (x >> 25 & 1) + (x >> 26 & 1) + (x >> 27 & 1) + (x >> 28 & 1) + (x >> 29 & 1) +
        (x >> 30 & 1) + (x >> 31 & 1);
}

具有一些优化的版本:

int leftmost_ones(int x)
{
    x = ~x;
    x |= x >> 16;
    x |= x >> 8;
    x |= x >> 4;
    x |= x >> 2;
    x |= x >> 1;
    x = ~x;

    return (x & 1) + (x >> 1 & 1) + (x >> 2 & 1) + (x >> 3 & 1) + (x >> 4 & 1) + 
        (x >> 5 & 1) + (x >> 6 & 1) + (x >> 7 & 1) + (x >> 8 & 1) + (x >> 9 & 1) + 
        (x >> 10 & 1) + (x >> 11 & 1) + (x >> 12 & 1) + (x >> 13 & 1) + (x >> 14 & 1) +
        (x >> 15 & 1) + (x >> 16 & 1) + (x >> 17 & 1) + (x >> 18 & 1) + (x >> 19 & 1) +
        (x >> 20 & 1) + (x >> 21 & 1) + (x >> 22 & 1) + (x >> 23 & 1) + (x >> 24 & 1) +
        (x >> 25 & 1) + (x >> 26 & 1) + (x >> 27 & 1) + (x >> 28 & 1) + (x >> 29 & 1) +
        (x >> 30 & 1) + (x >> 31 & 1);
}

答案 1 :(得分:1)

你能使用循环吗?

int mask = 0x80000000;
int count = 0;
while (number & mask) {
    count += 1;
    mask >>= 1;
}

答案 2 :(得分:1)

你可以这样做:

int result = clz(~x);

即。反转所有位,然后计算前导零。

clz返回前导零位数(通常也称为ffsnlz) - 有关实施详情,请参阅此处:http://en.wikipedia.org/wiki/Find_first_set#Algorithms

答案 3 :(得分:1)

我认为这是可行的,基本上是展开典型的循环并且通常很烦人。

这个怎么样:当且仅当答案为1时,表达式为1?我提供:

const int ok1 = !((number & 0xc0000000) - 0x800000000);

!和减法可以解决有人打破我们键盘上的==键的问题。

然后,当且仅当anwer为2时,表达式为1:

const int ok2 = !((number & 0xe0000000) - 0xc0000000);

如果你继续形成这些,最后的答案是他们的总和:

const int answer = ok1 + ok2 + ... + ok32;

顺便说一下,我似乎不记得在我上学的时候被给予这些奇怪的限制任务,我想时间已经改变了。 :)

答案 4 :(得分:0)

int count_consecutive_bits(unsigned int x) {
    int res = 0;
    while (x & 0x80000000) { ++res; x <<= 1; }
    return res;
}