二进制

二进制(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

位运算

运算符 作用
\ | 位或
& 位与
^ 位异或
<< 位左移
&#62;&#62; 位右移
~ 位取反

上面就是常见的运算符。下面讲解具体的运算:

| 位或 (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

&nbsp;&nbsp;&nbsp;&nbsp; 0101 移位

0001 删位

结果:1

位右移运算符 ( >> ) :使指定的二进制位都右移指定的位数,右移指定位之后,右边低位的数值将被移出并丢弃,左边高位空出的职位用 0 补齐

5<<2

0000 0101

0001 01 移位

0001 0100 补位

结果:20

Mysql位运算简化一对多关系

1
2
3
4
5
6
7
8
这个举个例子:这边涉及到位运算,首先我们先假设一个6位二进制,0代表关闭,1代表开启
0 0 0 0 0 0 #这代表全关闭
0 0 0 0 0 1 #只开启1 二的零次方 1
0 0 0 0 1 0 #只开启2 二的一次方 2
0 0 0 1 0 0 #只开启3 二的二次方 4
0 0 1 0 0 0 #只开启4 二的三次方 8
0 1 0 0 0 0 #只开启5 二的四次方 16
1 0 0 0 0 0 #只开启6 二的五次方 32

所以,运用这个技巧,首先字段的值都要是以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
2
$a << $b    Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
1
2
3
4
5
6
那么反转,给你一个7如果解读,
(7 & 1) > 1 => (7 & (1 << 0)) > 1
(7 & 2) > 1 => (7 & (1 << 1))> 1
(7 & 4) > 1 => (7 & (1 << 2))> 1
位运算会转成2进制,而&的特性是都要为1才为1,这边的1,2,4都是只有一个位置为1,其他都为0。
这样就可以通过是否为1判断。