表达式"b=(b-x)&x"的含义是什么?

6

假设x是一个集合,以下代码遍历了集合x的所有子集:

int b = 0;
do {
// process subset b
} while (b=(b-x)&x);

我读到一篇关于位运算和如何使用它来表示集合的文章。

表达式 b=(b-x)&x 的含义是什么?它如何工作? 我熟悉 ==,但不熟悉在 do while 循环中出现 =。这是如何工作的?当 (b-x)&x 的值变成零时,循环是否终止?

该代码的用法如下:

#include <iostream>

using namespace std;

void subsets(int x, int b){
    do{
        cout << b<<"\n";
    }while(b = (b-x)&x);
}

int main()
{
    int x = (1<<1)|(1<<3)|(1<<4)|(1<<8);
    int b = 0;
    subsets(x, b);
    return 0;
}

以上代码的输出结果是:
0
2
8
10
16
18
24
26
256
258
264
266
272
274
280
282

4
赋值的值是被赋的值。非零整数为“真”,零为“假”。 - molbdnilo
1
x 到底是什么?它的类型是什么?它在哪里声明?它的初始值是多少?在循环体中它如何变化? - Bathsheba
2
请提供一个 [mre]。 - Alan Birtles
1
请编辑您的问题以包含一个 [mcve]。不需要下载一本书并搜索示例来理解问题。问题应该是自包含的。 - 463035818_is_not_a_number
这里描述了链接:_"所有内置的赋值运算符都返回*this"_。这意味着b = a是一个操作(其中int b; int a;),它返回对b的引用。 - Thomas Sablik
1个回答

3

先解决简单的问题:

当 (b-x)&x 的值变为零时,循环结束吗?我熟悉 == 运算符,但不知道 = 在 do while 循环中的作用。这是如何工作的?

是的。

像这样的 do/while 循环:

do{
    cout << b<<"\n";
}while(b = (b-x)&x);

以下步骤:
  1. 执行cout << b<<"\n";
  2. 执行b = (b-x)&x并记住结果。
  3. 如果结果不为零,则返回第1步。
=是赋值运算符。它将一个变量设置为一个值,例如i = 0;。但是...赋值的结果是什么?在C语言中,赋值的结果是被赋值的值。这使得您可以编写a = b = c = 0;,以将三个变量abc设置为0。这相当于a = (b = (c = 0));,即它将c设置为0,然后将b设置为该结果,最后将a设置为该结果。(在C++中,可能会编写一个不遵循这个规则的类,但我们只处理int类型,而不是类)
有些人喜欢使用这个技巧使他们的代码更短。相反,您也可以像下面这样编写它:
do{
    cout << b<<"\n";
    b = (b-x)&x;
}while(b);

表达式b=(b-x)&x是什么意思?
“=”代表赋值,“-”代表减法,“&”代表二进制“与”运算。
这个表达式从b中减去x,然后对结果进行位“与”运算,并将答案赋给b。
什么是二进制“与”运算?二进制“与”运算是指将两个数字按位对齐,对每个对应的位执行逻辑“与”操作,生成一个新的数字。如果两个输入中的位都是1,则相应位为1,否则为0。例如:
    01011010 = 90
  & 11101000 = 232
  -----------------
    01001000 = 72

所以,90和232是72。

它是如何工作的?

该程序基本上将数字视为二进制。在x中,每个比特位都是1表示“在集合中”,或者是0表示“不在集合中”。

b然后通过所有可能的比特组合。 b = (b-x) & x; 是一种“巫术魔法”,用于按顺序将组合更改为下一个组合,例如:

  - 000000000 <- b the first time
    011001001 <- x
 -----------------
    100110111 <- b-x
  & 011001001 <- x
 -----------------
    000000001 <- (b-x)&x (b the second time)
  - 011001001 <- x
 -----------------
    100111000 <- b-x
  & 011001001 <- x
 -----------------
    000001000 <- (b-x)&x (b the third time)
  - 011001001 <- x
 -----------------
    100111111 <- b-x
  & 011001001 <- x
 -----------------
    000001001 <- (b-x)&x (b the fourth time)
 ...etc...

你可以肯定,发明这个技巧的人非常聪明。


回答你关于 '=' 和 '==' 的问题,'=' 是赋值操作符,而 '==' 则是比较操作符,在 C++ 中无论在哪里使用都是如此。 - szMuzzyA
@szMuzzyA bool MyClass::operator =(MyClass const& b) {return thingy == b.thingy;} - user253751
@user2553751 这是一个被重载的运算符(一种欺骗),它不适用于原始类型。无论是否重载为执行其他操作,'='仍然被称为赋值运算符。 - szMuzzyA
1
答案仍然缺乏为什么这个公式有效的洞察。 - AlwaysLearning
@AlwaysLearning 你需要非常详细地了解二进制数学。我不确定是否存在介于“哇,那是魔法”和“噢,那很琐碎”的层次。 - user253751
1
我在这里提供了它的工作原理的见解:https://dev59.com/IcTra4cB1Zd3GeqP0TW-#71931730。实际上,逻辑并不太复杂。 - McKinley

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