N 和 (1<<x) == 什么时候为真?
When does N & (1<<x) == true?
我最近一直在研究使用位运算生成子集的完整搜索,所以我偶然发现了以下代码:
for(int b = 0; b < (1<<n); b++) {
vector<int> subset;
for(int i = 0; i < n; i++) {
if( b&(1<<i)) subset.push_back(i);
}
//use subset here
}
此代码用于查找一组n
元素的所有子集。我对这部分感到困惑
b&(1<<i)
如果b
的第 i 位是0
,这显然是错误的,但我不明白为什么如果第 i 位b
是true
的,为什么它会true
,我的意思是结果不会只是2
i
的幂(因为它不等于 1,即真的, 应该返回false
(?
变化:除此之外,我现在注意到我知道任何与零不同的数都被认为是true
,如果x
是0
而N
是奇数,或者x>0
和N
是偶数,则N & (1<<x) == true
为真,因为==
优先于&
,所以N & (1<<x) == true
解析为N & ( (1<<x) == true )
你有一个小小的误会...
因为它不等于 1,即 true,应该返回 false(
事实是:只有0
被转换为false
而所有其他数字都变得true
。
如果
b
的第 i 位是0
,这显然是错误的,但我不明白为什么如果第 i 位b
是true
的,为什么它会true
,我的意思是结果不会2
i
的幂(因为它不等于 1,即真的, 应该返回false
(?
你在这里的错误不是1
是true
而所有其他的都是false
. 在 C++ 0
中false
,所有其他值都true
。
回想一下,当在 C 或 C++ 中使用数值表达式时,在需要逻辑表达式的地方(如 if
s 或 while
s(中使用数值表达式时,表达式结果将隐式地与零进行比较。返回零的表达式表示"假",而返回非零的表达式表示"真"。他们不需要返回1
*。
现在回想一下,1 << i
构造一个二进制表示的数字,该数字在第 i 个位置有一个1
。当位置 i
处的第 b
位为零时,执行具有此类数字b
的数字&
将产生零。当位置i
位b
为 1 时,表达式将生成一个非零值,该值被 if
语句解释为"true"。
* 当 C 或 C++ 计算一个逻辑表达式时,例如 !
或 &&
时,它会产生1
,而不是任意的非零数。
这是一个非常常见的混淆,你混合了两件事:
- 布尔到整数的转换:
true
转换为 1,false
转换为 0 - 整数到布尔值的转换:0转换为
false
,其他任何内容都转换为true
。
因此,当您使用表达式时,结果int
if
或while
或任何其他需要布尔值的语句,您将隐式将其转换为bool
因此第二种情况。此代码:
if( b&(1<<i)) subset.push_back(i);
在逻辑上与:
bool flag = b&(1<<i);
if( flag ) subset.push_back(i);
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 程序什么时候会创建多个堆
- 调用boost.asio的异步函数时,线程是什么时候创建的
- Swig/python : 什么时候需要 SWIG_init() ?
- 什么时候 std::initializer_list 是微不足道的可构造的?