算法
常用运算符(PHP)
算数运算符
+
-
*
/
%
比较运算符
>
<
==
>=
<=
!=
===
!==
逻辑运算符
!
&&
||
赋值运算符
=
三元运算符
?...:
??
?:
字符串拼接
.
引用
&
位运算符
&
|
^
~
<<
>>
在PHP中整除、N次方使用函数,算术运算建议使用bc函数
& 与运算符,全1为1,否则为0
1 & 1 = 1
2 & 2 = 2
1 & 2 = 0
| 或运算符,有1为1,全0为0
1 | 1 = 1
2 | 2 = 2
1 | 2 = 3
^ 异或运算符,不同为1,相同为0
任何数异或0都等于它本身
- 10 ^ 0 = 10
任何数异或它本身都等于0
- 10 ^ 10 = 0
任何数异或全为1的2进制数都等于它取反(1s表示全为1的二进制数,等于~0)
- 10 ^ 1s = ~10
任何数异或它的取反都等于全为1的二进制数
- 10 ^ ~10 = 1s
两次异或能够还原原值,三次异或能够在不借助第三个变量的情况下,交换两个变量
- 1 ^ 1 = 0
- 2 ^ 2 = 0
- 1 ^ 2 = 3
~ 取反运算符
~1 = -2
1的2进制,以8位为例,最高为表示正、负,为:0000 0001
所以它取反后的值是,1111 1110,最高位为1,所以它是负数
负数在计算机中要补码存储,符号位不变,其它位取反后加1,即:1000 0010<< 左移运算符
1 << 1 = 2 0000 0001 -> 0000 0010 往左移动一位,低位补0
1 << 2 = 4 0000 0001 -> 0000 0100 往左移动两位,低位补0
左移公式 x << n = x * (2^n)
>> 右移运算符
对于无符号数,高位补0;有符号数,各编译器不一样,有的补符号位(算术右移),有的补0(逻辑右移)
右移公式 x >> n = x / (2^n)
正数右移动
- 10 >> 1 = 5 0000 1010 -> 0000 0101 往右移动一位,高位补0
- 10 >> 2 = 2 0000 1010 -> 0000 0010 往右移动两位,高位补0
负数右移,先补码(符号位不变,其它位取反后加1),右移(高位补1),再补码
-10 >> 1 = -5
1. 先补码 1000 1010 -> 1111 0110
2. 右移1位(高位补1)1111 0110 -> 1111 1011
3. 再补码 1111 1011 -> 1000 0101
-10 >> 2 = -3
1. 先补码 1000 1010 -> 1111 0110
2. 右移2位(高位补1)1111 0110 -> 1111 1101
3. 再补码 1111 1101 -> 1000 0011
>>> 无符号右移运算符(PHP没有无符号右移运算符)
运算逻辑和右移运算符一样,只是高位忽略正负,永远补零
常用位运算(Python)
# 将x最右边的n位清零,x & (~0 << n)
x = int('10101000', 2) # 168
print(x & (~0 << 4)) # 160,10100000,全为1的数左移4位再与操作
# 获取x的第n位值(0或1),(x >> n) & 1
x = int('10101000', 2) # 168
print((x >> 3) & 1) # 1,右移3位后,最后面的1跟1与
# 获取x的第n位的幂值,x & (1 << (n - 1))
x = int('10101000', 2) # 168
print(x & (1 << (4 - 1))) # 8,1左移3位为8(1000),再与x相与,则结果为0或幂值
# 仅将第n位置为1,x | (1 << n)
x = int('10101000', 2) # 168
print(x | (1 << 2)) # 172,1左移动2位(100),再与x相或,则右数第3位肯定为1,相当于168+4
# 仅将第n位置为0,x & ~(1 << n)
x = int('10101000', 2) # 168
print(x & ~(1 << 3)) # 160,1左移3位(1000),取反(0111),再与x相与,则右数第4位肯定为0,其他不变
# 将x最高位至第n位(包含n,n是从右往左数的)清零,x & ((1 << n) - 1)
x = int('10101000', 2) # 168
print(x & ((1 << 4) - 1)) # 8,1左移4位(10000),减1(01111),再与x相与,把高位全部打掉,只有1000保留下来了
# 不管x为几,与上1后,要么为1,要么为0(结果只和第0位相关)
x = int('10101000', 2) # 168
print(x & 1) # 0
# 清零最低位的1,不管x为几,减1后,最低位的1变为0,后面的0依次变为1
x = int('10101000', 2) # 168
print(x & (x - 1)) # 160,减1:10101000 -> 10100111
# 得到最低位的1,x & -x(如果是奇数,那最后位肯定是1)
x = int('10101000', 2) # 168
print(x & -x) # 8,-x=~x+1,取反10101000 = 01010111,再加1 = 01011000,与原值相与
# x与取反值相与,结果肯定为0
x = int('10101000', 2) # 168
print(x & ~x) # 0