算法

常用运算符(PHP)

  1. 算数运算符 + - * / %

  2. 比较运算符 > < == >= <= != === !==

  3. 逻辑运算符 ! && ||

  4. 赋值运算符 =

  5. 三元运算符 ?...: ?? ?:

  6. 字符串拼接 .

  7. 引用 &

  8. 位运算符 & | ^ ~ << >>

  9. 在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

results matching ""

    No results matching ""