PHP中的位运算与位移运算(其它语言通用)

/*
        PHP中的位运算与位移运算
=======================
二进制Binary:0,1
逢二进1,易于电子信号的传输
原码、反码、补码
二进制最高位是符号位:0为正数,1为负数(左边是高位)

原码:二进制表示的数为原码
对于正数:原码反码补码都一样
1 ----> 0000000 00000000 00000000 00000001
对于负数:
反码:原码的符号位不变,其它位取反
补码:对负数的反码+1
-1原码: ---> 10000000 00000000 00000000 00000001
-1反码: ---> 11111111 11111111 11111111 11111110
-1补码: ---> 11111111 11111111 11111111 11111111
(0的反码补码都是0)

PHP中的数据类型都是有符号的
计算机运算的时候,都是以补码的方式来运算的
(不写是正数还是负数,都会被转成补码,然后进行运算)

PHP4个位运算符:(所有语言通用)
按位与&        两位全为1,则结果为1
按位或|        两位有1,则结果为1
按位异或^    两位一个为0,一个为1,结果为1
按位取反~    0变1,1变0

PHP中的移位运算符:
算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
算术左移<<:符号位不变,低位补0

*/
echo "<h4>PHP位运算</h4>";
$n1=~2;
echo "$n1"."<br/>";// -3
/*
对2取反推导:
2的原码=反码=补码:
00000000 00000000 00000000 00000010
取反得补码:(计算机是以补码的方式来运算的)
11111111 11111111 11111111 11111101
得最高位为1,则是一个负数的补码,由补码推原码:减1,取反得原码
10000000 00000000 00000000 00000011
二进制原码转十进制,结果为:-3
 */

$n2=~-5;
echo "$n2"."<br/>";//4
/*
对-5取反推导:
-5的符号位是1
获取其原码:
10000000 00000000 00000000 00000101
获取反码:(符号位不变,其它位取反)
11111111 11111111 11111111 11111010
获取补码:(反码加1)
11111111 11111111 11111111 11111011
对补码取反:(符号位是0为正数,正数的原码=反码=补码)
00000000 00000000 00000000 00000100
得正数:4
 */

$n3=2&3;
echo "$n3"."<br/>";//2
/*
推导:
按位与& :两位全为1,则为1
获取2和3的补码(因为是正数:原码=反码=补码)
2   00000000 00000000 00000000 00000010
3   00000000 00000000 00000000 00000011
按位与:
2&3:00000000 00000000 00000000 00000010
获得结果为正数补码:2
 */

$n4=2|3;
echo "$n4"."<br/>";//3
/*
推导:
按位或|:两位有1,则为1
获取2和3的补码(因为是正数:原码=反码=补码)
2   00000000 00000000 00000000 00000010
3   00000000 00000000 00000000 00000011
按位或:
2&3:00000000 00000000 00000000 00000011
获得结果为正数补码:3
 */

$n5=2^3;
echo "$n5"."<br/>";//1
/*
推导:
按位异或^:两位不同则为1,否则为0
获取2和3的补码(因为是正数:原码=反码=补码)
2   00000000 00000000 00000000 00000010
3   00000000 00000000 00000000 00000011
按位或:
2&3:00000000 00000000 00000000 00000001
获得结果为正数补码:1
 */

$n6=-3^3;
echo "$n6"."<br/>";//1
/*
推导:
获取-3的补码:
-3原码:10000000 00000000 00000000 00000011
-3反码:11111111 11111111 11111111 11111100

-3补码:11111111 11111111 11111111 11111101
获取3的补码:
3 补码:00000000 00000000 00000000 00000011

按位异或:
-3^3    11111111 11111111 11111111 11111110
因为结果是负数的补码,则需要获取其原码:
反码    11111111 11111111 11111111 11111101

原码    10000000 00000000 00000000 00000010
得结果为:-2
 */

echo "<h4>PHP位移运算</h4>";
// 算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
// 算术左移<<:符号位不变,低位补0

$a1= 1>>2;
echo "a1=.$a1"."<br/>";//0
/*
推导:
算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
1的二进制向右移动两位,用符号位0补高位的两个空缺
00000000 00000000 00000000 00000001
1>>2:
00000000 00000000 00000000 00000000
结果:0
 */

$b1=-1>>2;
echo "b1=.$b1"."<br/>";//-1
/*
推导:
算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
-1的的补码:
原码:10000000 00000000 00000000 00000001
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
-1>>2:相当于
      11111111 11111111 11111111 11111111
得结果补码再取原码为:-1
 */

$c1=1<<2;
echo "c1=.$c1"."<br/>";//4

/*
推导:
算术左移<<:符号位不变,低位补0
1的补码:00000000 00000000 00000000 00000001
1<<2: 左移两位,低位补0   (相当于1*2*2)
         00000000 00000000 00000000 00000100
得结果补码再取原码为:4
 */


$d1=-1<<2;
echo "d1=.$d1"."<br/>";//-4
// (相当于-1*2*2) 结果为:-4
// 推导:
// 算术左移<<:符号位不变,低位补0
// -1的补码:11111111 11111111 11111111 11111111
// -1<<2: 左移两位,低位补0 
// 得结果
// 补码 11111111 11111111 11111111 11111100
// 反码 11111111 11111111 11111111 11111011
// 原码 10000000 00000000 00000000 00000100
// 结果:-4

?>
原文地址:https://www.cnblogs.com/lt-style/p/3489784.html