对整数存储不了解的读者请猛击《整数在内存中是如何存储的,为什么它堪称天才般的设计》。
MySQL 中的整数字面量(常量整数,也就是直接书写出来的整数)默认以 8 个字节(Byte)来表示,也就是 64 位(Bit)。例如,5 的二进制形式为:0000 0000 ... 0000 0101
省略号部分都是 0,101 前面总共有 61 个 0。运算符 | 说明 | 使用形式 | 举例 |
---|---|---|---|
| | 位或 | a | b | 5 | 8 |
& | 位与 | a & b | 5 & 8 |
^ | 位异或 | a ^ b | 5 ^ 8 |
~ | 位取反 | ~a | ~5 |
<< | 位左移 | a << b | 5 << 2,表示整数 5 按位左移 2 位 |
>> | 位右移 | a >> b | 5 >> 2,表示整数 5 按位右移 2 位 |
&
、|
、~
和逻辑运算中的&&
、||
、!
非常相似。
|
运算的两个二进制位有一个为 1 时,结果就为 1,两个都为 0 时结果才为 0。例如1|1
结果为 1,0|0
结果为0,1|0
结果为1,这和逻辑运算中的||
非常类似。mysql> SELECT 10|15,9|4|2; +-------+-------+ | 10|15 | 9|4|2 | +-------+-------+ | 15 | 15 | +-------+-------+ 1 row in set (0.00 sec)10 的补码为 1010,15 的补码为 1111,按位或运算之后,结果为 1111,即整数 15;9 的补码为 1001,4 的补码为 0100,2 的补码为 0010,按位或运算之后,结果为 111,即整数 15。
mysql> SELECT -7|-1; +----------------------+ | -7|-1 | +----------------------+ | 18446744073709551615 | +----------------------+ 1 row in set (0.00 sec)-7 的补码为 60 个‘1’加 1001,-1 的补码为 64 个‘1’,按位或运算之后,结果为 64 个‘1’,即整数 18446744073709551615。
&
运算的两个二进制位都为 1 时,结果就为 1,否则为 0。例如1|1
结果为 1,0|0
结果为 0,1|0
结果为 0,这和逻辑运算中的&&
非常类似。mysql> SELECT 10 & 15,9 & 4 & 2; +---------+-----------+ | 10 & 15 | 9 & 4 & 2 | +---------+-----------+ | 10 | 0 | +---------+-----------+ 1 row in set (0.00 sec)10 的补码为 1010,15 的补码为 1111,按位与运算之后,结果为 1010,即整数 10;9 的补码为 1001,4 的补码为 0100,2 的补码为 0010,按位与运算之后,结果为 0000,即整数 0。
mysql> SELECT -7&-1; +----------------------+ | -7&-1 | +----------------------+ | 18446744073709551609 | +----------------------+ 1 row in set (0.01 sec)-7 的补码为 60 个‘1’加 1001,-1 的补码为 64 个‘1’,按位与运算之后,结果为 60 个‘1’加 1001,即整数 18446744073709551609。
^
运算的两个二进制位不同时,结果为 1,相同时,结果为 0。例如1|1
结果为 0,0|0
结果为 0,1|0
结果为1。mysql> SELECT 10^15,1^0,1^1; +-------+-----+-----+ | 10^15 | 1^0 | 1^1 | +-------+-----+-----+ | 5 | 1 | 0 | +-------+-----+-----+ 1 row in set (0.00 sec)10 的补码为 1010,15 的补码为 111,按位异或运算之后,结果为 0101,即整数 5;1 的补码为 0001,0 的补码为 0000,按位异或运算之后,结果为 0001;1 和 1 本身二进制位完全相同,因此结果为 0。
mysql> SELECT -7^-1; +-------+ | -7^-1 | +-------+ | 6 | +-------+ 1 row in set (0.00 sec)-7 的补码为 60 个‘1’加 1001,-1 的补码为 64 个‘1’,按位异或运算之后,结果为 110,即整数 6。
expr << n
其中,n 指定值 expr 要移位的位数,n 必须为非负数。mysql> SELECT 1<<2,4<<2; +------+------+ | 1<<2 | 4<<2 | +------+------+ | 4 | 16 | +------+------+ 1 row in set (0.00 sec)1 的补码为 0000 0001,左移两位之后变成 0000 0100,即整数 4;4 的补码为 0000 0100,左移两位之后变成 0001 0000,即整数 16。
mysql> SELECT -7<<2; +----------------------+ | -7<<2 | +----------------------+ | 18446744073709551588 | +----------------------+ 1 row in set (0.00 sec)-7 的补码为 60 个‘1’加 1001,左移两位之后变成 56 个‘1’加 1110 0100,即整数 18446744073709551588。
expr >> n
其中,n 指定值 expr 要移位的位数,n 必须为非负数。mysql> SELECT 1>>1,16>>2; +------+-------+ | 1>>1 | 16>>2 | +------+-------+ | 0 | 4 | +------+-------+ 1 row in set (0.00 sec)1 的补码为 0000 0001,右移 1 位之后变成 0000 0000,即整数 0;16 的补码为 0001 0000,右移两位之后变成 0000 0100,即整数 4。
mysql> SELECT -7>>2; +---------------------+ | -7>>2 | +---------------------+ | 4611686018427387902 | +---------------------+ 1 row in set (0.00 sec)-7 的补码为 60 个‘1’加 1001,右移两位之后变成 0011 加 56 个‘1’加 1110,即整数 4611686018427387902。
mysql> SELECT ~1,~18446744073709551614; +----------------------+-----------------------+ | ~1 | ~18446744073709551614 | +----------------------+-----------------------+ | 18446744073709551614 | 1 | +----------------------+-----------------------+ 1 row in set (0.00 sec)常量 1 的补码为 63 个‘0‘加 1 个’1‘,位取反后就是 63 个’1‘加一个’0‘,转换为二进制后就是 18446744073709551614。
mysql> SELECT BIN(~1); +------------------------------------------------------------------+ | BIN(~1) | +------------------------------------------------------------------+ | 1111111111111111111111111111111111111111111111111111111111111110 | +------------------------------------------------------------------+ 1 row in set (0.01 sec)1 的补码表示为最右边位为 1,其他位均为 0,取反操作之后,除了最低位,其他位均变为 1。
mysql> SELECT 5 & ~1; +--------+ | 5 & ~1 | +--------+ | 4 | +--------+ 1 row in set (0.00 sec)逻辑运算
5&~1
中,由于位取反运算符‘~’的级别高于位与运算符‘&’,因此先对 1 进行取反操作,结果为 63 个‘1’加一个‘0’,然后再与整数 5 进行与运算,结果为 0100,即整数 4。
本文链接:http://task.lmcjl.com/news/13884.html