我们之前学过逻辑与(&&)      条件1 && 条件2 当两边条件同时成立时候返回1

逻辑或(||)         条件1 || 条件2    当两边条件只要有一个成立时候返回1

一. & 按位与

只有对应的两个二进制位均为1时候,结果位才会是1,否则为0.

举例: 比如9&5,其实就是1001&101 = 1,因此9&5=1

   计算过程

1001
0101
---------
0001

  php代码

echo  9&5;   //1

  

二.  |   按位或

只要对应的两个二进制位有一个为1时,结果位就位1,否则为0。

举例: 比如9|5,其实就是1001 | 101 = 1,因此9|5=13;

1001
0101
---------
1101

  

三. ^ 按位异或 

对应二进制位相异(不相同)时,结果位1,否则为0.

    举例: 比如9^5,其实就是1001^ 101 = 1,因此9^5=12
1001
0101
---------
1100

  

echo  9^5;  // 12

如果自己异或自己呢

1001
1001
---------
0000

就是0

那用自己在异或0

1001
0000
---------
1001

得到的还是自己。

根据上面分析得到如下规律

相同整数^的结果是0,比如5^5=0

多个整数相^的结果跟顺序无关,比如5^6^7 = 5^7^6

任何数值跟0进行异或,结果还是等于原来的数值,比如 9^6^9 = 9^9^6 = 0^6 = 6

应用:

根据上面原理,加密算法中,可以使用使用异或运算符进行加密与解密,在二进制运算中,如果将一个明文的二进制位与密钥进行按位“异或”运算,将得到密文,将此密文与密钥再次进行按位“异或”运算,又可以得到明文。这样,只需编写一个函数便可以同时完成加密和解密两种运算。

四. ~ 按位取反

 把每个二进制位取反,它是单目运算符,只操作一个数。

举例: ~9  把9每个二进制位取反。

~0000 0000 0000 0000     0000 0000 0000  1001
1111 1111 1111 1111 1111 1111 1111 0110 开头第一个数是符号位 这里得出为负数

 

echo  ~9;   // -10

五. << 位运算左移  

把整数的各个二进制位全部左移n位,高位要放弃,低位补0,左移n位其实就是乘以2的n次方。

由于左移位是丢弃最高位,0补最低位,所以符号位也要丢弃,左移后的结果可能会改变正负性

举例:  <<9

下面用0做参考

  0000 0000 0000 0000 0000 0000 0000 0000
000 0000 0000 0000 0000 0000 0000 1001

  

将9左移一位,最高位也就是红色的0出来,然后被舍弃,低位补0如下

0000 0000 0000 0000 0000 0000 0000 0000
000 0000 0000 0000 0000 0000 0000 1000

计算出9左移一位后的值是

echo  9<<1;  //18

在计算下

echo  9<<2;  //36       相当于 9*4=18      在相当于  9*2的2次方
echo 9<<3; //72 相当于 9*6=72 在相当于 9*2的3次方
echo 9<<4; //144 相当于 9*16=144 在相当于 9*2的4次方

得出规律

9 << n  = 9*2的n次方

所以可以引申计算的时候,比如 9*6 就是等于  9<<3,而且位运算比较快。

注意一点,最高位如果是1倍丢弃,后面那一位是0,所以会影响正负性的。

六. >> 位运算右移 

把整数的各个二进制位全部右移n位,保持符号位不变,右移n位其实就是除以2的n次方。

为正数时,符号位为0,最高位补0。

为负数时,符号位为1,最高位是补0或者补1,这取决于编译系统的规定。

举例:  把9右移一位,如下,由于保持符号位不变,左边第二个是空,右边第一个被移出来

   0000 0000 0000 0000 0000 0000 0000 0000
00 0000 0000 0000 0000 0000 0000 1001

然后空出来的用符号位补齐,这里符号位是0,所以就用0补齐,如下

 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 100
echo  9>>1;  //4
echo 8>>1; //4 8右移一位也等于4

右移和左移也有规律

echo  8>>1;  //
echo 8>>2; //
echo 8>>3; //1  

得出

8>>n   等于8/2的n次方

七,利用位操作来实现变量值的互换
我们一般交换两个变量的值都是利用一个临时变量来存储中间的值

$a = 10;
$b =12;
$temp = $a;
$a = $b;
$b = $temp;
echo sprintf("a=%d,b=%d",$a,$b);//a=12,b=10  

或者

$a = $b - $a;
$b = $b - $a;
$a = $b + $a;
echo sprintf("a=%d,b=%d",$a,$b);//a=12,b=10

位运算   利用异或^的规则  a^b^a == a^a^b == b

$a = $a ^ $b;
$b = $a ^ $b;
$a = $a ^ $b;
echo sprintf("a=%d,b=%d",$a,$b);//a=12,b=10

结果也是一样的

八.利用位运算判断奇偶性

一般用取模的方法来判断是否是奇偶数
比如:
10%2 == 0 那么就是偶数 否则是奇数

根据查看 二进制中 最后一位如果是1那么就是奇数 ,如果是0那么就是偶数。如下:
         15 的而二进制数 : 0000 1111

9  的而二进制数 : 0000 1001

14 的而二进制数 : 0000 1110

10 的而二进制数 : 0000 1010

位于运算,只有当对应的二进制数都是1的时候才是1,否则为0

$a & 1 == 1 //奇数

$a & 1 == 0 //偶数

 

运算符号
意义
运算对象类型
运算结果类型
实例
~
非运算
整型,字符型
整型
~a
&
与运算
a & b
|
或运算
a | b
^
异或运算
a ^ b
<<
位左移运算
a<<4
>>
位右移运算
a>>2

  

使用位运算案例:

1.两数字求和

//两数字相加 (不支持小数)
function add($num1, $num2)
{
if ($num1 == 0) {
return $num2;
}
if ($num2 == 0) {
return $num1;
}
$XORresult = $num1 ^ $num2;
$carry = ($num1 & $num2)<<1;
return add($XORresult,$carry);
} echo add(3,2); //5

2.php 函数error_reporting() 设置 PHP 的报错级别并返回当前级别。

error_reporting(E_ALL & ~E_NOTICE)

错误报告是按位的,先取得 E_ALL 的值(二进制)然后 再取得 E_NOTICE 的值(二进制),然后在通过 ~ 将其取反。

error_reporting(E_ALL ^ E_NOTICE);//显示除去 E_NOTICE 之外的所有错误信息 。
 error_reporting(E_ALL^E_WARNING^E_NOTICE);//显示除去E_WARNING E_NOTICE 之外的所有错误信息 。

05-17 07:39