关于位运算的新发现

关于位运算的新发现(2021年06月22日)


发现历程

2021年06月21日晚上,在做算法题的时候遇到了二进制的位运算相关内容,位运算包括与运算、或运算、异或运算、取反等等。

我感觉平时在编程的时候更多的是主要用加减乘除以及求余数运算,在位运算这方面比较欠缺和薄弱,于是我打算先探索一下二进制位运算中的 与运算 的规律。

与运算方法

6 & 2 = 2

6 的二进制表示是 110, 2的二进制表示是 10

所以按位与运算就是

110
010
---
010

每一个位相互比较,如果都是1,那么这一位的结果就是1,其他情况就是 0

结果是 010,就是2

我打算把所有数字与所有数字的与运算写出来,就像九九乘法表一样,做成一个16x16的表格,看看有没有规律

手写表格草稿

(由于是草稿,写的字比较潦草)

好像是有一点规律,但是表格太大了,看着也不够整齐,于是我想用编程的方式直接输出,这样更加方便

for i in range(16):
    for j in range(16):
        n = i & j
        print(n, end="\t")
    print()

输出结果

0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
0   1   0   1   0   1   0   1   0   1   0   1   0   1   0   1   
0   0   2   2   0   0   2   2   0   0   2   2   0   0   2   2   
0   1   2   3   0   1   2   3   0   1   2   3   0   1   2   3   
0   0   0   0   4   4   4   4   0   0   0   0   4   4   4   4   
0   1   0   1   4   5   4   5   0   1   0   1   4   5   4   5   
0   0   2   2   4   4   6   6   0   0   2   2   4   4   6   6   
0   1   2   3   4   5   6   7   0   1   2   3   4   5   6   7   
0   0   0   0   0   0   0   0   8   8   8   8   8   8   8   8   
0   1   0   1   0   1   0   1   8   9   8   9   8   9   8   9   
0   0   2   2   0   0   2   2   8   8   10  10  8   8   10  10  
0   1   2   3   0   1   2   3   8   9   10  11  8   9   10  11  
0   0   0   0   4   4   4   4   8   8   8   8   12  12  12  12  
0   1   0   1   4   5   4   5   8   9   8   9   12  13  12  13  
0   0   2   2   4   4   6   6   8   8   10  10  12  12  14  14  
0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  

右下角的两位数部分好像有一点奇怪的形状,

输出

于是我继续扩大范围,发现了这所有二位数的部分似乎组成了一个奇妙的形状!这让我想起了分形结构。

于是我觉得应该还可以再直观可视化一些,于是我就让程序输出成一张图片,我们都知道图片通常是有像素点矩阵组成的像素点,矩阵里的数字可以用像素点的亮度,也就是灰度来表示,这样就更加直观了。

于是我改了一下代码,由于像素点太小了,我顺便也扩大了表格的边界到256

N = 256
im = Image.new('RGBA', (N, N), (0, 0, 0))
for i in range(N):
    for j in range(N):
        n = i & j
        im.putpixel((i, j), (n, n, n))
im.show()
与运算256x256

图片出现了明显的分形结构,越白的地方就是数字越大的地方。纯黑的像素是0。

我改变边长,将256扩展到2048,由于有些数字太大了,就导致是纯白了。这里的分形结构就变得更明显了。

位运算2048x2048

由于颜色的表示方式是 三个数 (r, g, b),r表示红色,g表示绿色,b表示蓝色,r,g,b三个数字的取值范围都是在[0, 256)。

我上面用亮度表示的方法是:n为一个数字,则颜色表示为:(n, n, n)

其实还可以随意修改将数字转化为颜色的方式,比如 n<255时候只有蓝色分量的颜色 即 (0, 0, n),在 n < 255x2 的时候,把它多出255的部分加到另一个颜色的分量上等等……

于是就可以有这样的图案

修改了颜色显示方式

白色的部分,居然还出现了谢尔宾斯基三角形,这是一个著名的分形结构。看来这个矩阵里隐藏的规律很多呀。

随后我又在256边长、正常灰度的输出颜色的规则下,看了或运算

或256x256

以及异或运算

异或256x256

他们在整体上似乎都有相似的纹理,但是有各有各的不同。

目前看来,与运算比或运算的图片暗淡,因为与运算中的结果大小不可能超过参与运算的两个数的大小。而或运算可以。

异或运算的图片,有一条明显的黑色的缝隙,这也很符合异或运算的特点,当参与运算的两个数一样的时候,没有任何一个位数是不同的,所以运算的结果就是0。

二进制似乎总是隐藏这各种各样的规律。我还需要继续学习。

你可能感兴趣的:(关于位运算的新发现)