我们先了解一下位异或的运算法则吧:

1、a^b = b^a。
2、(a^b)^c = a^(b^c)。

3、a^b^a = b。
对于一个任意一个数 n,它有几个特殊的性质:

1、0^n = n。

2、n^n = 0。

3、1^n = !n。(即 n==0 时,则所得的值为真,当 n != 0,所得值为 0,即为假)

按位异或的 3 个特点:

(1) 0^0=0,0^1=1  0 异或任何数=任何数
(2) 1^0=1,1^1=0  1 异或任何数 = 任何数取反
(3) 任何数异或自己=把自己置 0

 /*

手册资料:

位运算符

位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值

$a ^ $b Xor (按位异或) 将把 $a 和 $b 中不同的位设为 1

*/

 ^(按位异或)的运算实例

#数字之间位运算
echo 12 ^ 9;      // 输出为 '5'
 
#字符串之间位运算
echo "12" ^ "9"; // 输出退格字符(ascii 8)
                 // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello";    // 输出 ascii 值 #0 #4 #0 #0 #0
                           // 'a' ^ 'e' = #4
echo 2 ^ "3"; // 输出 1
              // 2 ^ ((int)"3") == 1
echo "2" ^ 3; // 输出 1
              // ((int)"2") ^ 3 == 1
分析:在定义中我们可以知道,位运算符允许对 “整型” 中指定的位进行置位。但是也不仅仅只是支持 “整数”, 还支持字符串,不过如果左右参数都是字符串,则位运算符将操作 “字符的 ASCII 值”, 也就是如果是字符串,将转变成字符相应的 ASCII 然后再进行操作.

#对与字符串操作,根据上面分析,原理总结如下:
$aa= 'a'^'b';
$bb= chr(ord('a')^ord('b'));
var_dump($aa);
var_dump($bb);
#以上两种写法结果是一样的

 

按位异或的几个常见用途:
(1) 使某些特定的位翻转
    例如对数 10100001 的第 2 位和第 3 位翻转,则可以将该数与 00000110 进行按位异或运算。
       10100001^00000110 = 10100111

(2) 实现两个值的交换,而不必使用临时变量。
    例如交换两个整数 a=10100001,b=00000110 的值,可通过下列语句实现:
    a = a^b;   //a=10100111
    b = b^a;   //b=10100001
    a = a^b;   //a=00000110

(3) 在汇编语言中经常用于将变量置零:
    xor   a,a

(4) 快速判断两个值是否相等
    举例 1: 判断两个整数 a,b 是否相等,则可通过下列语句实现:
        return ((a ^ b) == 0)

5  应用通式:

  对两个表达式执行按位异或。

  result = expression1 ^ expression2

  参数 result   任何变量。expression1   任何表达式   ^ expression2  任何表达式。

说明
  ^ 运算符查看两个表达式的二进制表示法的值,并执行按位异或。该操作的结果如下所示:

  0101     (expression1) 1100     (expression2)----1001     (结果) 当且仅当只有一个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0。  只能用于整数

位运算

  •   计算机里面所有的信息都是整数,所有的整数都可以表示成二进制的,实际上计算机只认识二进制的. 位运算就是二进制整数运算啦. 
  •   位运算时把数字用二进制表示之后,对每一位上 0 或者 1 的运算。理解位运算的第一步是理解二进制。二进制是指数字的每一位都是 0 或者 1. 比如十进制的 2 转化为二进制之后就是 10。
  •   其实二进制的运算并不是很难掌握,因为位运算总共只有 5 种运算:与、或、异或、左移、右移。如下表:

 

 

与(&)

0 & 0 = 0

1 & 0 = 0

0 & 1 = 0

1 & 1 = 1

或(|)

0 | 0 = 0

1 | 0 = 1

0 | 1 = 1

1 | 1 = 1

异或(^)

0 ^ 0 = 0

1 ^ 0 = 1

0 ^ 1 = 1

1 ^ 1 = 0

位取反(~)

~$m

 

 

 

向左移位(<<)

$m << $n

 

 

 

向右移位(>>)

$m >> $n

 

 

 

 

小提示

正数的原码,反码、补码都是一样的,负数不一样

  原码:数字的 8 位 二进制,符号位(第一位)为 0 表示正数,为 1 表示负数

  反码:正数反码与原码一样,负数的反码是符号位 1 不变,整数的每一位二进制数位求反,得到反码

     补码:正数补码与原码一样,负数反码的符号位 1 不变,按位取反,末尾(最低位)加 1;计算机中的运算都是以补码的形式运算的,存储也是补码

   补码的特性:
    1、一个负整数(或原码)与其补数(或补码)相加,和为模。
    2、对一个整数的补码再求补码,等于该整数自身。
    3、补码的正零与负零表示方法相同。

对比

 

含义

php

C 语言

Java

按位与

$a & $b 

a & b

a & b

按位或

$a | $b

a | b

a | b

按位异或

$a ^ $b

a ^ b

a ^ b

按位取反

~$m

~a

~a

左移

$m << $n

a << b

a << b

带符号右移

$m >> $n

a >> b

a >> b

无符号右移

a>>> b