位运算
二进制
二进制(binary)在数学和数字电路中指以2为基数的记数系统,以2为基数代表系统是二进位制的。
简单的理解就是满二进一位,每一位只可能是0或1。
以1,2,3,4为例,1就是1; 而2在1的基础上加1,位满2进一位,所以前面新增一位是1,之前的栏位因为进位所以为0,二进制就是1 0;那么,3的情况就是在2的末位加上1,所为为 1 1; 最后,4在3的末位加1,末位满2需要往倒数第二位进位加1,末位则为0,倒数第二位因为末位进位也满2进位,所为为0,新增一位为1,就是 1 0 0 。
位运算
| 运算符 | 作用 |
|---|---|
| \ | | 位或 |
| & | 位与 |
| ^ | 位异或 |
| << | 位左移 |
| >> | 位右移 |
| ~ | 位取反 |
上面就是常见的运算符。下面讲解具体的运算:
| 位或 (1遇0保存1)
举例:10 | 15
10 转二进制 1010
15 转二进制 1111
1010
1111
1111
结果:15
& 位与(1遇0保存0)
举例:10 &15
10 转二进制 1010
15 转二进制 1111
1010
1111
1010
结果:10
位异或运算符 ( ^ ) :对应的二进制位不相同时,结果为 1 ,否则为 0
举例:10 ^15
10 转二进制 1010
15 转二进制 1111
1010
1111
0101
结果:5
位取反运算符 ( ~ ) :将对应的二进制数逐位反转,即 1 取反后变 0 , 0 取反后变 1
~5
5 二进制 101,补满 32位
00000000000000000000000000000101
按位取反
11111111111111111111111111111010
由于32位开头第一个是1,所以这是一个负数,将 二进制转换成负数,需要先反码
00000000000000000000000000000101
之后,再+1
00000000000000000000000000000110
转换成十进制为6,加上符号变成负数 -6;
所以,简单理解就是~5 等于5+1然后前头变负数。
同理~1 等于-2,
~-2 等于1(-2+1=-1;负号变正号等于1)。
位左移运算符 ( << ) :使指定的二进制位都左移指定的位数,左移指定位之后,左边高位的数值将被移出并丢弃,右边低位空出的位置用 0 补齐
5>>2
0101
0101 移位
0001 删位
结果:1
位右移运算符 ( >> ) :使指定的二进制位都右移指定的位数,右移指定位之后,右边低位的数值将被移出并丢弃,左边高位空出的职位用 0 补齐
5<<2
0000 0101
0001 01 移位
0001 0100 补位
结果:20
Mysql位运算简化一对多关系
1 | 这个举个例子:这边涉及到位运算,首先我们先假设一个6位二进制,0代表关闭,1代表开启 |
所以,运用这个技巧,首先字段的值都要是以2的N次幂为基础,如下:
1,2,4,8,16,32,64,128,512,1024,2048,4096…
然后,把上面的每一个值当做一个属性。多个属性就进行累加,然后记录合。
为什么是2的N次幂呢?
因为这种情况下每个元素的二进制都有且仅有一个栏位为1,为1的栏位也都是不同的,赋予其独特性。而这种独特性有多奇妙,就要往下看了。
这个技巧适用于属性较少的一对多的场景,可以存储1个或者多个。
– 添加一个分类 用 “|”SELECT (4|2|1); 4+2+1= 7 7代表这4,2,1三个属性。
0001
0010
0100
0111
为什么可以直接相加呢?因为”|”是有1则为1,你会发现(当然是2的N次幂这种),用“|”会增加一个为1的栏位,好巧这些值又都只是二进制只有一个栏位为1的值。
– 去掉一个分类,用“^”SELECT 7 ^ 1; 7-1=6 6代表4,2这两个数据(不相同时,结果为 1 ,否则为 0)
0111
0001
0110
– 当我们需要查询某个月份的景点时,例如查询3月份的景点,可使用以下语句:
SELECT * FROM spots WHERE month & 4 = 4;
– 当设置某个景点适合某个月份时,例如设置4325的景点适合2月份,可使用下面的语句:
UPDATE spots SET month = month | 2 WHERE id = 4325
– 当取消设置某个景点的月份时,可使用下面的语句:
UPDATE spots SET month = month ^ 2 WHERE id= 4325
– 查询同时适合多个月份的数据,例如需要查询设置了11,12,1月份的景点,将其三个月份对应的数值加起来,结果为6145,然后使用这个数值进行查询:
SELECT * FROM spots WHERE month & 6145 = 6145
– 查询只要适合,1,11,12月份其中一个月份的景点就行
SELECT * FROM spots WHERE (month & 4096 = 4096) or (month & 2048 = 2048) or (month & 1 = 1)
php运用
1 | $a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。 |
1 | 那么反转,给你一个7如果解读, |

