学习内容来自:
https://www.runoob.com/w3cnote/bit-operation.html
目录
二元运算符
& 位于
两十进制数,转换为二进制,按位比较,两个都为1才为1,否则为0,再把二进制结果转换为十进制,得到最终结果。
(有0则0,全1才1)
| 位或
两个都为0为0,否则为1。
(有1则1,全0才0)
^ 异或
两个不同时为1,否则为0。
注:与0相异或值不变。
(同0异1)
<< 左移
x << y -- 将x转换为二进制,所有位向左偏移y位,若不足y位补0。
>> 右移
x >> y -- 与左移类似,不同的是:若x是非负数,高位补0;若x是负数,则高位补1。
e.g.: 1100 >> 3 == 1
一元运算符
~按位取反
对当前数字转换为二进制以后,1变0,0变1。
位运算的用途
清零
与一个各位都为零的数值相与,结果为零。
取一个二进制数的指定位
比如取数 X=1010 1110 的低4位,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行&按位与运算(X&Y=0000 1110)即可得到X的指定位。
x & 1,x | 0 都可以得二进制x的某位。
前者在lsb水印中的使用例:
(编码时改变原图r、g最后一位为0,再将数字水印按位与最后一位的0进行 | 或运算,就可以将数字水印嵌入图片r、g值中)
# 将两个数值的二进制表示依次嵌入到前10个像素的R和G通道的最低有效位中
for i in range(10):
pixel = list(pixels[i])
pixel[0] = (pixel[0] & 0xFE) | int(bin_num1[i]) # R通道。前面不变,最后一位变0。
pixel[1] = (pixel[1] & 0xFE) | int(bin_num2[i]) # G通道
pixels[i] = tuple(pixel) # 将修改后的像素值放回到像素列表中
后者在lsb水印中的使用例:
(解码时将原图r、g &按位与1,得到r、g最后一位,即嵌入的数字水印。)
# 获取前10个像素的R和G通道的LSB
n1 = ""
n2 = ""
pixels = list(img.getdata())[:10]
for pixel in pixels:
r_lsb = pixel[0] & 1
g_lsb = pixel[1] & 1 # 返回的是十进制,下面再转换为字符串以连接
n1 += str(r_lsb)
n2 += str(g_lsb)
判断奇偶
最未位为0就是偶数,为1就是奇数。
故可用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。
把一个数据的某些位设置为1
比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。
翻转指定位
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。