位运算在PHP应用中用得不多,这节课的内容作为以了解为主。学会并理解位运算,对提高编程思想有很大帮助。
1、位运算符都是针对整数的二进制数字形式而进行的。
2、按位与运算基本规则(规则表):
1 & 1 ==> 1
1 & 0 ==> 0
0 & 1 ==> 0
0 & 0 ==> 0;
3、 按位或运算基本规则
1 | 1 ==> 1;
1 | 0 ==> 1;
0 | 1 ==> 1
0 | 0 ==> 0
4、按位非运算:
~ 1 ==> 0
~ 0 ==> 1
5、按位异或运算:
1 ^ 1 ==> 0
0 ^ 0 ==> 0
1 ^ 0 ==> 1
0 ^ 1 ==> 1
规律:相同就是0,不同就是1
形式: A & B; //A和B都是数字,其实是常规的10进制数字,但内部会按二进制进行计算
含义: 将A和B的二进制形式的每一个位上的二进制数字进行按位与(&)运算之后的结果。
说明:一个数字的二进制形式通常是32位的0和1的组合,也可能是64位,但未了说明问题,我们通常只用8位。
举例:
$r1 = 9 & 13; //9的二进制是“1001”,13的二进制是“1101”
数字9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
数字13 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
结果$r1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
可见结果是“00001001”,即9
形式: A | B; //A和B都是数字,其实是常规的10进制数字,但内部会按二进制进行计算
含义: 将A和B的二进制形式的每一个位上的二进制数字进行按位或(|)运算之后的结果。
举例:
$r1 = 18 | 10; //18的二进制是“10010”,23的二进制是“1010”
数字18 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
数字10 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
结果$r1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
可见结果是“00011010”,即26
形式:
A << n; //A是一个要被移动的数字,同样可以是普通数字,但按二进制去运算,n是一个指定要移动的位数
含义:
将数字A的二进制形式的每一个位上的数字往左边移动指定的位数n,则最左边的n位移出去了就不管了,最右边空出来的n位,补0就可以。
举例:
$r1 = 9 << 2; //9的二进制形式为:1001
数字9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
左移2位 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
结果 | 0 | 0 | 25 | 0 | 0 | 22 | 0 | 0 |
可见结果是:32 + 4 = 36
形式:
A >> n; //A是一个要被移动的数字,同样可以是普通数字,但按二进制去运算,n是一个指定要移动的位数
含义:
将数字A的二进制形式的每一个位上的数字往右边移动指定的位数n,则最右边的n位移出去了就不管了,最左边空出来的n位,补0就可以(对正数,实际是补符号位)。
举例:
$r1 = 9 >> 2; //9的二进制形式为:1001
数字9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
右移2位 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
结果 | 0 | 0 | 0 | 0 | 0 | 0 | 21 | 0 |
结果就是:2
结果:
将一个数字的二进制形的每一个二进制数字取反所得到的结果。
将2个整数的二进制形式的每一个对应数字进行异或运算之后的结果。
通过学习按位与、按位或运算,上面这两种运算也不难理解。
位运算应用实例:
开关状态:就是某种数据,它只有2个值可用:true,false,1,0, 开,关。。。。。
一组事物是指,多个数据的的任意可能的出现状态。
我们假设有5个灯泡的开关需要管理:
1,确定每个灯泡的状态:开,关;
2,可以指定打开任意一个灯泡;
3,可以指定关闭任意一个灯泡。
设定前提:这5个灯泡有明确的顺序,我们将设定5个变量(常量其实也行)。
假设1-5个灯泡的位置是从右往左边数——对应数字的位数
第1个灯泡:$d1 = 1; //00000001
第2个灯泡:$d2 = 2; //00000010
第3个灯泡:$d3 = 4; //00000100
第4个灯泡:$d4 = 8; //00001000
第5个灯泡:$d1 = 16; //00010000
则所有灯泡的总的状态,就可以使用一个变量来描述:比如:
如果$state = 7; //00000111 ,就表示第1,2,3灯泡亮
如果$state = 9; //00001001 ,就表示第1,4灯泡亮
如果$state = 13; //00001101 ,就表示第1,3,4灯泡亮
确定一个灯泡的开关状态:
$s1 = $state & $dn; //这里n表示1-5之间的任意一个。
则结果如果$s1大于0,就表示该灯泡亮,否则就表示该灯泡是灭的。
打开指定的灯泡
$state = $state | $dn; //这里n表示1-5之间的任意一个
关闭指定的灯泡
$state = $state & ~$dn; //这里n表示1-5之间的任意一个
结果:
扩充知识:
知道设置IP地址时有个子网掩码是做什么用的吗?IPv4中IP地址长度为32位,子网掩码也是32位,ip地址与子网掩码做按位与运算,就能求出网段。比如:
ip:192.168.1.108 & 子网掩码:255.255.255.0 =》 192.168.1.0
从 ip:192.168.1.0 至 192.168.1.255 这256个ip地址都处于同一网段192.168.1.x,任何一个ip与子网掩码:255.255.255.0 做按位与运算,都得出192.168.1.0。
ip:192.168.1.108 & 子网掩码:255.255.0.0 =》 192.168.0.0
从 ip:192.168.0.0 至 192.168.255.255 这65536个ip地址都处于同一网段192.168.x.x,任何一个ip与子网掩码:255.255.0.0 做按位与运算,都得出192.168.0.0。