查找重叠1位的计数

时间:2010-07-13 20:56:56

标签: c++ algorithm

我试图找到2个给定数字之间重叠的1位数。

例如,给定56

5 // 101
6 // 110

有1个重叠的1位(第一位)

我有以下代码

#include <iostream>
using namespace std;

int main() {
    int a,b;
    int count = 0;
    cin >> a >> b;
    while (a & b != 0) {
        count++;
        a >>= 1;
        b >>= 1;
    }
    cout << count << endl;

    return 0;
}

但是当我输入335123时,它返回7,但我认为这不正确

有人可以看到我的代码有问题吗?

4 个答案:

答案 0 :(得分:2)

您现有的算法只要在剩余的位中任何位来测试匹配,就会对每个位进行计数;因为123和335有一个共同的MSB,只要这两个数字都不为零,它就是真的。 123是较小的7位,所以它确实是7次,直到该数字被完全处理。作为极端情况,128(10000000)和255(11111111)将使用您的方法返回8,即使它实际上是1。

您希望将两个数字一起开始,然后计算该结果中的1的数量

答案 1 :(得分:2)

问题是你只是打印出任何位匹配的次数,因为你为每次迭代丢掉了最低有效位(最大值是为较小的数字设置的位)。你正在比较[a] BITWISE和[b]每次迭代的所有位。你可以通过使用1:a & b & 1进行屏蔽来纠正这个问题,这样当你每次向右移动东西时,你只是检查是否检查了最低有效位:< / p>

while (a && b){
    count += a & b & 1;
    a>>=1;
    b>>=1;
}

答案 2 :(得分:1)

您想要计算设置的位数。相反,您的代码有点计算二进制对数。

如果最低顺序位置位,则仅递增计数。

for (int c = a & b; c != 0; c >>= 1) {
  if (c & 1)
    ++count;
}

答案 3 :(得分:0)

略短的形式:

int countCommonBits(int a,int b) {    
    int n = 0;
    for (unsigned v = (unsigned)(a & b); v; v >>= 1) {
        n += 1 & v;
    }
    return n;
}

如果您知道这两个数字都是正数,则可以省略使用无符号类型。注意当使用“int”时,在负数右移的符号扩展会给你一些过度计数(即无限循环)。

很久以后...... 回顾一下旧的答案,发现了这一点。当前“接受”的答案是1)效率低下,2)如果数字是负数则是无限循环。 FWIW。