如何确定一个数字';使用C的二进制表示?

如何确定一个数字';使用C的二进制表示?,c,bit-manipulation,parity,C,Bit Manipulation,Parity,关于计算一个数字中有多少个1s,已经存在一些问题,但这个问题是关于判断1是偶数还是奇数 不允许使用任何循环或条件(包括开关)语句。此外,应避免使用除法、乘法或模运算符。更具体地说,我们可以假设它是一个32位无符号整数 事实上,我已经有了一个实现,但我无法找出它工作的原因。任何证明其正确性的证据或任何新想法都将非常有用 int even_ones(unsigned x) { x ^= x>>16; x ^= x>>8; x ^= x>>4

关于计算一个数字中有多少个
1
s,已经存在一些问题,但这个问题是关于判断1是偶数还是奇数

不允许使用任何循环或条件(包括开关)语句。此外,应避免使用除法、乘法或模运算符。更具体地说,我们可以假设它是一个32位无符号整数

事实上,我已经有了一个实现,但我无法找出它工作的原因。任何证明其正确性的证据或任何新想法都将非常有用

int even_ones(unsigned x)
{
    x ^= x>>16;
    x ^= x>>8;
    x ^= x>>4;
    x ^= x>>2;
    x ^= x>>1;

    return !(x & 1);
}
快速计算字节或字的奇偶校验。具体哪种方法最快取决于您的CPU以及不同基本操作之间的相对速度。因此,如果这是您的应用程序的瓶颈,您应该分析每个应用程序,以找出哪一个在您的目标机器上运行得最好

您的解决方案与实现非常相似,只是最后没有巧妙的优化。这里发生的事情是,在每一步,你将一半的位与另一半的位进行异或运算,直到你只剩下一位。如果有偶数个1,则字的奇偶性为0,如果有奇数个1,则字的奇偶性为1;或者等价地,一个字的奇偶校验就是该字中所有位的异或


由于XOR运算符是可交换和关联的,因此我们可以重新排序字中所有位的XOR方式。因此,我们不是通过将每个位分别异或到结果中来计算所有位的异或,而是将高半位与低半位异或,将我们关心的位数减少一半;当剩下一位时,我们就完成了。

我假设您知道异或操作的作用-如果将两位设置为相同的值,则结果为
0
,否则为
1
。所以当我有两个一位数字A和B时,如果A和B都是
0
,或者都是
1
,那么
A^B
将是零。换句话说,
A
B
中的值之和是偶数

现在让我们一次做两位:C和D是两位数字。以下是可能的组合:

C    D    C^D
00   00   00   even
01   00   01    odd
10   00   10    odd
11   00   11   even
00   01   01    odd
01   01   00   even
10   01   11   even
11   01   10    odd
00   10   10    odd
01   10   11   even
10   10   00   even
11   10   01    odd
00   11   11   even
01   11   10    odd
10   11   01    odd
11   11   00   even
如您所见-每个实例中的操作都会将位数减少一半,如果以奇数开始,则产生的
1
位数是奇数(因为
1
s对相互抵消,但其他所有对都不变)

现在,很明显,当你从更大的数字(4位,8位,16位)开始时,为什么同样的事情仍然是真的。本质上,您的算法从一个32位数字开始,并将其拆分为两个16位数字。通过去掉“双1”,它将比特数减少了一半;然后对剩下的一半进行操作,并重复,直到只剩下一个位。通过测试该位是1(奇数)还是0(偶数),您可以得到答案

如果不清楚,像
x^=x>>16这样的操作实际上会将前16位移到下16位,并在那里产生异或。它实际上并没有清除最上面的部分,所以“留下了一片混乱”。但算法忽略了接下来的混乱。请参见以下内容(为了简单起见,从8位开始):

在这种情况下,最后一个数字
y
r
q
的异或,它们依次是
l,j
k,i
的异或;依次是
h,d
f,b
g,c
,和
e,a
的异或。如您所见,您最终得到了所有位的XOR;正如我上面解释的,这意味着“全偶数”或“全奇数”,这取决于最低有效位现在是
1
还是
0


我希望这会有所帮助。

请注意,此异或将最高有效16位与最低有效16位进行比较:

x ^= x>>16;
然后,该系列继续进行第二个最低有效8位与最低有效4位的异或运算,请注意,最高有效16位现在只是垃圾,无论发生什么都可以忽略:

x ^= x>>8;
如此,我们继续将第二个最低有效4位与最低有效4位进行异或运算,直到得到1位;到目前为止,除了最低有效位以外的所有位都是垃圾,最后一行只需使用按位and with 1即可获得最低有效位并翻转它进行均匀性测试

也许,如果你这样写的话,更容易理解:

int even_ones(unsigned x)
{
    a = (x ^ x>>16) & 0x0000FFFF;
    b = (a ^ a>>8)  & 0x000000FF;
    c = (b ^ b>>4)  & 0x0000000F;
    d = (c ^ c>>2)  & 0x00000003;
    e = (d ^ d>>1)  & 0x00000001;
    return !(e&1);
}
为什么这样做有效?因为XOR相当于不带进位的位加法。

希望这有帮助:

   enum {
      EVEN,
      ODD
    } even_odd;

unsigned int check_even_odd_no_of_ones(unsigned int num)
{
  if(num_of_ones(num) & 1)
    return ODD;
  else
    return EVEN;
}

谢谢

这并不能真正回答问题。我想,这只是逻辑而已。这里没有提到完整的代码。。
   enum {
      EVEN,
      ODD
    } even_odd;

unsigned int check_even_odd_no_of_ones(unsigned int num)
{
  if(num_of_ones(num) & 1)
    return ODD;
  else
    return EVEN;
}