K&R C 编程语言练习 2-9

  • 本文关键字:练习 编程语言 c
  • 更新时间 :
  • 英文 :


我不理解练习2-9,在k& r c编程语言中,第2章,2.10:

练习2-9。在两个的补充编号系统中,x& =(x-1)在x中删除了最右边的1位。解释为什么。使用此观察值编写更快的BitCount版本。

BitCount功能是:

/* bitcount: count 1 bits in x */
int bitcount(unsigned x)
{
    int b;
    for (b = 0; x != 0; x >>= 1)
        if (x & 01)
            b++;
    return b;
}

该函数在检查是否是位1之后删除最右数,然后在最后一个位弹出。

我不明白为什么 x&(x-1)删除正确的1位?例如,假设x是 1010和x-1是二进制中的 1001,而 x&(x-1)将是 1011,所以最右边的位会在那里,我会在其中,我错了吗?

另外,练习提到了两个人的补充,它与这个问题有关吗?

非常感谢!

首先,您需要相信k& r是正确的。其次,您可能会对这些单词有一些错误的理解。

让我再次为您澄清。最右1位并不意味着最大的位,而是最多的位,最多的位是二进制形式的1个。

让我们任意假设x是xxxxxxx1000(x可以是0或1)。然后从右到左,第四位是"最右边的1位"。根据这种理解,让我们继续解决问题。

为什么x& =(x-1)可以删除最右边的1位?

在两个的补体编号系统中,-1用所有1个位模式表示。

因此,X-1实际上是X (-1),即XXXXXX1000 1111111111。这是棘手的点。

在最大的1位1位之前,所有0变为1,最右的1位变为0,并且有一个携带1的左侧。而且,这1将继续延伸到左侧并引起溢出,同时,所有" x"位仍然是一个,因为'x' '1' '1'(随身携带)导致a'x'bit。

然后x&(X-1)将删除最右边的1位。

希望您现在可以理解。

谢谢。

这是解释它的简单方法。让我们任意假设y是xxxxxxx1000(x可以是0或1)。

xxxxxxx1000-1 = xxxxxxxx0111

xxxxxxxx1000&xxxxxxxx0111 = xxxxxxxx0000(请参阅"最右边的1"。)

因此,y& =(y-1)的重复数量在y变为0 之前将是y。

的总数

为什么 x & (x-1)删除正确的订单位?只需尝试查看:

如果最高订单位为1,则X具有a...b1的二进制表示,x-1a...b0,因此位并给出a...b1,因为and1 & 00

,因为公共位不变。

其他X具有a...b10...0的二进制表示;x-1a...b01...1,出于与上述x & (x-1)相同的原因,a...b00...0将再次清除最右的订单位。

因此,您只需读取操作x = x & (x-1),直到x为0:步骤数将是1位的数量,而不是扫描所有位以找到哪个是0,哪个是1,而不是扫描。它比幼稚的实现更有效,因为从统计学上讲,您将使用一半的步骤。

代码的示例:

int bitcount(unsigned int x) {
    int nb = 0;
    while (x != 0) {
        x &= x-1;
        nb++
    }
    return nb;
}

ik我已经很晚了(≈3.5yr),但是您的示例有错误。


x = 1010 = 10
x -1 = 1001 = 9
1010&1001 = 1000

您可以看到,它在10中删除了最右边的位。

7 = 111
6 = 110
5 = 101
4 = 100
3 = 011
2 = 010
1 = 001
0 = 000

观察到最右1的位置在任何数字中,该数字的相同位置的位为0。因此,用X-1的x将重置(即设置为0)最右边的位。

7 & 6 = 111 & 110 = 110 = 6
6 & 5 = 110 & 101 = 100 = 4
5 & 4 = 101 & 100 = 100 = 4
4 & 3 = 010 & 011 = 010 = 2
3 & 2 = 011 & 010 = 010 = 2
2 & 1 = 010 & 001 = 000 = 0
1 & 0 = 001 & 000 = 000 = 0

最新更新