位运算符

位运算一览表

符号 示例 含义
& $a & $b 按位与。将 $a 和 $b 中都为 1 的位设为 1
| $a | $b 按位或。将 $a 和 $b 中任何一个为 1 的位设为 1
^ $a ^ $c 按位异或。将 $a 和 $b 中相同位不一致的位设为 1
~$a ~$a 按位取反。将 $a 为 1 的位设为 0,为 0 的位设为 1
<< $a << $c 左移。将 $a 的位向 移动 $b 次
>> $d >> $b 左移。将 $a 的位向 移动 $b 次

& 运算符

按位与。相同为 1,不同为 0

$a = 1; // 0001
$b = 2; // 0010
echo $a & $b; // 0000

按位比较,相同位得1,不同位得 0。由于 1 和 2 的二进制数中每个位都不相同,所以结果为: 0000,也就是 0。

| 运算符

按位或。有 1 为 1,无 1 为 0

$a = 1; // 0001
$b = 3; // 0011
echo $a | $b; // 0011

按位比较,相同位得 0 ,不同位 得 1,所以结果为: 0011,也就是 3。

^ 运算符

按位异或。相同为 0,不同为 1

$a = 1; // 0001
$b = 3; // 0011
echo $a ^ $b; // 0010

按位比较,相同位得 0 ,不同位 得 1,所以结果为: 0010,也就是 2。

~ 运算符

按位取反。1 取 0,0 取 1

$a = 1; // 0000 0000 0000 0000 0000 0000 0000 0001
$a1 = ~$a;
echo $a1; // -2。 

这个运算符相比较其它位运算符要复杂一些。我们知道,大多数编程语言中,最高位是符号位,那么,32 位操作系统下,PHP 整数的最大值是:

0111 1111 1111 1111 1111 1111 1111 1111 = 2147483647

因此,当对 1 进行按位取反后,得到

$A1 = 1111 1111 1111 1111 1111 1111 1111 1110

符号位为 1,即为 负数。在计算机中,负数以其对应绝对值的补码形式表达。也就是说,$a1 的补码是 $A1,则

反码 = 补码 - 1 = 1111 1111 1111 1111 1111 1111 1111 1101

那么 $a1 对应的整数就是:

原码 = 反码各位取反 = 0000 0000 0000 0000 0000 0000 0000 0010 = -2;

<< 运算符

各位向左移动,末尾补 0

$a = 2; // 0000 0000 0000 0000 0000 0000 0000 0010
$a1 = $a << 3;
echo $a1; // 16

32 位系统下,一个整数用 32 位表示。当位数向左移动,舍去多余的位数,末尾补 0 ,则得到 $a1 为:

0000 0000 0000 0000 0000 0000 0001 0000 = 16

因此

$a << $b = $a^($b+1) // $a 的 ($b + 1) 次方

左移运算符有一个比较有趣的地方,当一个数向左移动超过计算机指定整数位时,就会出现不符合我们上述总结的原数平方规则的情况。比如 2 在 64 位系统下,向左移动 62、63、64 位:

echo 2 >> 61 // 4611686018427387904
echo 2 >> 62 // -9223372036854775808
echo 2 >> 63 // 0
echo 2 >> 64 // 0

有兴趣的朋友可以列出对应二进制数,推演下计算过程。

>> 运算符

各位向右移动,前面补 0

$a = 8; // 0000 0000 0000 0000 0000 0000 0000 1000
$a1 = $a << 3;
echo $a1; // 16

左移和右移运算符“误区”

关于左移和右移运算符,很多朋友可能会看到这样的总结:

左移平方,右移开方

其实严格来说,这只针对值为 2 的正整数次幂的整数有效。当不是 2 的正整数次幂时,比如:

$a = 9; // 0000 0000 0000 0000 0000 0000 0000 1001
$a1 = $a >> 1;
echo $a1; // 4

所以,遇到左移和右移运算符时,要实际情况实际分析,不能一味的按照别人的总结走。

原文地址:https://www.cnblogs.com/BeiGuo-FengGuang/p/9835203.html