多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 二进制的特性 * 只有 0 和 1 组成, 逢二进一,借一当二 *二进制中有原码,反码,补码的概念 *正数的原码,补码,反码都是它本身 *0 的原码,反码,补码都是它本身 *负数的的反码是原码的位数取反,即 0=》1, 1=》0 *负数的补码是反码加+1 *在二进制当中,最高位代表数的正负,0 代表正数, 1 代表负数 *在PHP当中的位运算,都是以补码的形式进行的 *在PHP当中,所有的数都是有符号的,即不考虑无符号数的情况 # 二进制位运算 1. `&`(位与):二进制中相对应的位都是 1 的位才为 1 ``` var_dump(2 & 3); 2 的原码,反码,补码 00000000 00000000 00000000 00000010 3 的原码,反码,补码 00000000 00000000 00000000 00000011 按位与 2&3 00000000 00000000 00000000 00000010 // 2 ``` 2. `|`(位或):二进制当中相对应的位只要有一个是 1 的位就为 1 ``` var_dump(2 | 3); 2 的原码,反码,补码 00000000 00000000 00000000 00000010 3 的原码,反码,补码 00000000 00000000 00000000 00000011 按位与 2|3 00000000 00000000 00000000 00000011 // 3 ``` 3. `~`(位取反):二进制中把相对应的位为 1 的取 0 ,为 0 的取 1 ``` var_dump(~3); var_dump(~2); 2 的原码,反码,补码 0 00000010 按位取反 ~2 1 11111101 最高位是1,是负数 得到反码 1 00000010 得到补码 1 00000011 // -3 1 * 1 + 1 * 2 3 的原码,反码,补码 0 00000011 按位取反 ~3 1 11111100 最高位是1,代表负 得到反码 1 00000011 得到补码 1 00000100 // -4 ``` 4. `^`(位异或):二进制当中相对应的位一个为 1 一个为 0 的位 才为 1 ``` var_dump(2 ^ 3); 2 的原码,反码,补码 00000000 00000000 00000000 00000010 3 的原码,反码,补码 00000000 00000000 00000000 00000011 按位异或 2^3 00000000 00000000 00000000 00000001 // 1 ``` 5. `<<`(位左移):将一个运算对象的各二进制位全部左移若干位(**左边的二进制位丢弃,右边补0**)。 设 a=1010 1110,`a = a<< 2` 将a的二进制位左移2位、右补0,即得a=1011 1000。 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。 ``` $a = -2; echo $a<<2; // 源码 $a = 10000000 00000000 00000000 00000010 // 反码 11111111 11111111 11111111 11111101 // 补码 11111111 11111111 11111111 11111110 反码 =》 补码 反码+1 // 左移两位,符号位不变,最高位移出,低位用0补齐 // 11111111 11111111 11111111 11111000 //补码的反码,补码减一 // 111111111 11111111 11111111 11110111 //反码的源码,符号位不变,取反 // 100000000 00000000 00000000 00001000 // -8 ``` 6. `>>`(位右移):将一个数的各二进制位全部右移若干位(**正数左补0,负数左补1,即左边用符号位补充,右边丢弃**)。 例如:a=a>>2 将a的二进制位右移2位,左补0 或者 左补1得看被移数是正还是负。 操作数每右移一位,相当于该数除以2。 `>>>`(位无符号右移):无符号右移,也叫逻辑右移(**若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0**)。 ``` echo -2>>3; //原码 10000000 00000000 00000000 00000010 //反码 11111111 11111111 11111111 11111101 //补码 11111111 11111111 11111111 11111110 //补码右移3位,符号位不变,最低位移出,移出位使用最高位符号位填充 // 11111111 11111111 11111111 11111111 //反码 11111111 11111111 11111111 11111110 //原码 10000000 00000000 00000000 00000001 // -1 echo -2>>>3; //原码 10000000 00000000 00000000 00000010 //反码 11111111 11111111 11111111 11111101 //补码 11111111 11111111 11111111 11111110 //补码右移3位,符号位不变,最低位移出,移出位使用0填充 // 00011111 11111111 11111111 11111111 //反码 00011111 11111111 11111111 1111111 //原码 00011111 11111111 11111111 1111111 // 536870911 ```