整理一下&、||、!的奇技淫巧
京东有一道笔试题
- /*************************************************************************
- > File Name: test.cpp
- > Author: Winter
- > Created Time: 2022年08月07日 星期日 16时12分42秒
- ************************************************************************/
-
- #include
-
- using namespace std;
-
- int func(int x)
- {
- int count = 0;
- while (x)
- {
- count++;
- x = x & (x - 1);
- }
- return count;
- }
-
- int main(int argc, char** argv)
- {
- cout << func(2015) << endl;
- return 0;
- }
就是x的二进制与x-1的二进制进行与运算;
再深挖一步,x-1的二进制就是把x的二进制的最右侧一个1变成0。
第一次 x & (x - 1)的结果就是把x最右侧的第一个1变成0(去掉1),再将结果赋值给x,计数器++;
......
所以 x & (x - 1)是统计x的二进制中有多少个1
上述代码结果

2015比1024大(2的10次方),但是小于2048(2的11次方)。
例如:
1 = (001)------->0 (从第0位开始计数,1在第0位)
2 = (010)------->1 (从第0位开始计数,1在第1位)
3 = (011)------->0 (从第0位开始计数,1在第0位)
4 = (100)------->2 (从第0位开始计数,1在第2位)
5 = (101)------->0 (从第0位开始计数,1在第0位)
......
首先从最低位开始判断,怎么判断呢?
想到与或非运算符。当x=1时,x&1才是1
- #include
-
- using namespace std;
-
- int func(int x)
- {
- int count = 0;
- int res = 1;
- while (1)
- {
- if (x & res) {
- break;
- }
- count++;
- res = res << 1;
-
- }
- return count;
- }
-
- int main(int argc, char** argv)
- {
- cout << func(1) << endl;
- cout << func(2) << endl;
- cout << func(3) << endl;
- cout << func(4) << endl;
- cout << func(5) << endl;
- return 0;
- }
结果

如果要计算具体是多少,用2累乘即可。
例如:
1 = (001)------->1 (从第0位开始计数,1在第1位)
2 = (010)------->0 (从第0位开始计数,1在第0位)
3 = (011)------->2 (从第0位开始计数,1在第2位)
4 = (100)------->0 (从第0位开始计数,1在第0位)
5 = (101)------->1 (从第0位开始计数,1在第1位)
......
- #include
-
- using namespace std;
-
- int func(int n) {
- int res = 0;
- while (n & 1) {
- n = n >> 1;
- res++;
- }
- return res;
- }
-
- int main(int argc, char** argv)
- {
- cout << func(1) << endl;
- cout << func(2) << endl;
- cout << func(3) << endl;
- cout << func(4) << endl;
- cout << func(5) << endl;
-
- return 0;
- }
结果

- #include
-
- using namespace std;
-
- int func(int n)
- {
- int pos=-1;
-
- while (n)
- {
- n>>=1;
- pos++;
- }
-
- return pos;
- }
-
- int main(int argc, char** argv)
- {
- cout << func(1) << endl;
- cout << func(2) << endl;
- cout << func(3) << endl;
- cout << func(4) << endl;
- cout << func(5) << endl;
-
- return 0;
- }
结果

这个是在leveldb源码中看到的三行代码
- const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
- static_assert((align & (align - 1)) == 0,
- "Pointer size should be a power of 2");
- size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1);
第一句:指针大小是4/8(32机器人是4字节,64位机器是8字节),所以align的值总是8
第二句:这是一句断言。如果一个数x,是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0。则(x-1)的二进制就是01111111.....1。则其与x与之后就是0,所以x&(x-1)) == 0为真,表明x是2的n次方,否则x不是2的n次方。
第三句:y & (x - 1),对应的y % x
注意:x必须是2的次幂。
未完待续......