什么是 (x & 1) 和 (x >>= 1)?

72

我正在尝试完成一个任务:“找出无符号整数数据类型中的位数,而不使用sizeof()函数。”

我的设计是将整数转换为位,然后计算它们。例如:10是10105是101

将整数转换为位表示显示了类似于这样的内容:

do
{ 
    Vec.push_back( x & 1 ) 
} 
while ( x >>= 1 );

我不想简单地复制粘贴。当我使用 F-10 时,我可以看到 (x & 1) 在做什么,但我不知道它的名称或者它是如何工作的(比较某些东西?)。另外,我知道 >= 表示“大于或等于”,但是 x >>= 1 是什么意思?

注意:标记为重复的问题是关于 JavaScript 而非 C++。


16
这个问题展示了研究的努力;它很有用且清晰。那么,这些粗鲁的评论是怎么回事?还有为什么会有人点踩? - Khalil Khalaf
14
我不理解所有的踩。 &>>=和其他操作符在互联网上搜索起来非常困难。对于已经见过这些操作符的人来说,这个问题很简单,但它们并不是自我解释的,当你第一次看到它们时可能会感到非常压抑。请问是否需要这段话的翻译? - Sergey Kalinichenko
8
好的标题。问题非常清晰。使用教科书可以很容易地回答,但使用在线资源可能会有困难。也许不值得点赞,但绝对不应该遭受如此严厉的抨击。 - user4581301
3
注意:虽然您的方法可能类似于您的教师真正想要的方法,但问题陈述是“查找无符号整数数据类型中的位数,而不使用sizeof()函数”,是关于查找一个_数据类型_ 的大小而不是一个_值_的。我认为您可以通过赋值-1来确保所有位都设置为1(当分配时会转换为最大可能的无符号整数),然后计算该值中的位数。 - davmac
7
教导人们查看JavaScript文档来学习C++运算符是一个非常糟糕的想法。 - Ben Voigt
显示剩余6条评论
5个回答

79

这些是位运算符(参考文献)。

x & 1的结果要么是1,要么是0,取决于x的最低有效位:如果最后一位是1,则x & 1的结果为1;否则,它为0。这是一个按位与操作。

x >>= 1的意思是“将x向右移动一位并将结果赋值给x”。该表达式计算出移位后x的新值。

注意:对于无符号类型的值,移位后最高有效位的值为零。对于有符号类型的值,最高有效位从移位前的符号位中复制而来,作为符号扩展的一部分,因此如果x是有符号类型且初始值为负数,则循环永远不会结束。


1
您好和谢谢。您能否请更详细地解释“(基于最后一位)”和“(向右移动一位)”? - Sandra K
我怀疑 @MaximEgorushkin 可能在暗示:负数的右移是否在最高位带入0或1是实现定义的。 - Ken Y-N
3
x >>= 1 这个表达式的意思是:1) 把 x 的值向右移动一位,2) 将新的值分配给 x,3) 返回 x 的新值作为整个表达式的值。如果没有第三步,那么这个 while 循环条件将毫无意义。 - Maxim Egorushkin
1
@MaximEgorushkin 这是一个很好的观点 - 复合赋值被用作表达式,而不是语句,因此知道表达式的值很重要。谢谢! - Sergey Kalinichenko
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Martin Bonner supports Monica
显示剩余2条评论

57

x & 1 相当于 x % 2

x >> 1 相当于 x / 2

因此,这些都是除以二的商和余数。


这是真的,在二进制补码中,对于有符号数是准确的。对于无符号数也是准确的。 - S.S. Anne
1
如果是 x | 1x<<1 呢?我很想知道。 - Safin Ghoghabori
@SafinGhoghabori 直到 0x3fffffff;1073741823 x<<1 是 x*2,但当值超过该范围时,它会给出负值,因为 MSB 变成了 1。如果 x 是奇数,则 x | 1 给出相同的值,否则为 x+1。 - Wimukthi Rajapaksha

25

除了“dasblinkenlight”的答案外,我认为举一个例子会更有帮助。为了更好的理解,我只使用8位二进制数。

 

x & 1 产生的值是 10,具体取决于 x 的最低有效位: 如果最后一位是 1x & 1 的结果是 1; 否则,它是 0。这是一种按位与操作。

这是因为在二进制中,1 会表示为 00000001。只有最后一位被设为 1。假设 x185,它在二进制中的表示是 10111001。如果你对 x 应用按位与操作,其中一个操作数是 1,那么结果将是:

00000001
10111001
--------
00000001

这个操作结果的前7位将在此操作后变为0且不携带信息(参见逻辑与操作)。因为无论操作数x的前7位是什么,在操作之后它们都将变成0。但是操作数1的最后一位是1,它将揭示操作数x的最后一位是0还是1。因此,在这个例子中,按位与操作的结果将是1,因为我们x的最后一位是1。如果最后一位是0,则结果也将是0,表示操作数x的最后一位是0

00000001
10111000
--------
00000000

x >>= 1 意思是将 x 右移一位并赋给自身。该表达式的值为移位后的 x 值。

我们以上面的例子为例说明。对于 x >>= 1,其表达的意思为:

10111001
--------
01011100

而对于左移操作 x <<= 1,它将会是:

10111001
--------
01110010
请注意用户“dasblinkenlight”在班次方面的注释。

很好的解释。谢谢!你能展示一个基本的现实问题,可以通过这些运算符来解决吗?除了OP中的例子之外?再次感谢。 - Sandra K
你可以使用这两个运算符来反转整数的位。请参见反转给定整数的位的第一个示例。在第一个示例中,将使用这两个运算符。移位运算符非常方便,可用于将数字乘以2或除以2:使用移位运算符将数字乘以2或除以2 - stackomatiker

6

这与 x = (x >> 1) 相似。

(operand1)(operator)=(operand2)  implies(=>)  (operand1)=(operand1)(operator)(operand2) 

它将x的二进制值向右移动一位。

例如:

int x=3;    // binary form (011) 
x = x >> 1; // zero shifted in from the left, 1 shifted out to the right:
            // x=1, binary form (001)

4

(n & 1) 可以判断一个数是奇数还是偶数,类似于 (n%2)。

  1. 如果 'n' 是奇数,(n & 1) 将返回 true/1;

  2. 否则将返回 false/0;


>> 在 (n>>=1) 中是一种位运算符,称为“右移位”,该运算符会修改 'n' 的值,公式为:

(n >>= m) => (n = n>>m) => (n = n/2^m)

阅读GeeksforGeeks关于"位运算符"的文章,推荐!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接