2. 从二进制到八进制

袁小进过年回家,收到了灵魂三问:

  • 有女朋友吗?
  • 有小孩儿吗?
  • 有工作了吗?

袁小进非常礼貌的回答各位叔叔阿姨:

“二婶,没有女朋友,没有小孩儿,我还没工作呢,您吃好”

“大姨,我还没工作呢,没有女朋友,没有小孩儿,我还没工作呢,您喝好”

“三姑,我还没工作呢,没有女朋友,没有小孩儿,我还没工作呢,您走好”

“......”

为了避免自己反复的回答同样的问题,聪明的袁小进想了一个办法:直接把灵魂三问的答案写在脑门儿上

但脑门儿就那么大,字如果写得太小,就看不太清

有什么办法,可以用最简单的文字回答问题呢?

袁小进首先想到,既然三个问题的顺序是固定的,每个问题的答案又只有“是”和“否”,干脆就简化一下,直接用三个字表达,比如:

“否否否”:没女朋友,没小孩,没工作

“是否是”:有女朋友,没小孩,有工作

“否是否”:没女朋友,有小孩(手动狗头),没工作 “...”

可是,在脑门上写字,毕竟是一种高技术含量的活儿,能不能不要那么多比划,再简单一点呢?

学过计算机的袁小进想到了二进制

二进制的每一位不刚好是“0”或“1”吗?那我何不用“0”表示“否”,用“1”表示“是”呢?

于是,文字变成了下面的格式:

“000”:没女朋友,没小孩,没工作

“101”:有女朋友,没小孩,有工作

“010”:没女朋友,有小孩(手动狗头),没工作

“...”

书写方便多了

可是,我们的袁小进同学还不满足,他还想获得更加简洁的写法

根据二进制的规律,一个N位的二进制可以表达2n个数字,范围是0 ~ 2n1

比如:

1位的二进制,可以表示0 1,共2【21】个数字,范围是0 ~ 1【211

2位的二进制,可以表示00 01 10 11,共4【22】个数字,范围是0 ~ 3【221

3位的二进制,可以表示000 001 010 011 100 101 110 111,共8【23】个数字,范围是0 ~ 7【231

那现在刚好是3位的二进制,无论是什么情况,袁小进都可以使用0~7之间的任何一个数来表示,比如:

“000”:用0表示,没女朋友,没小孩,没工作

“101”:用5表示,有女朋友,没小孩,有工作

“010”:用2表示,没女朋友,有小孩(手动狗头),没工作

“...”

明明可以用三个数字来书写,现在变成了一个数字即可表示,袁小进感觉生活更加美好了

此时,袁小进还发现了意外的惊喜

每一年回家可能情况都会有变化,变成一个数字书写后,就可以非常方便的在脑门上记录每一年的状况

现在一个数,顶过去三个数,再也不用担心灵魂三问了

而且,袁小进发现,这不就是在学校里学的八进制吗?

一个八进制数,每一位只有可能是0~7,共8个数字,逢8进一

一个八进制数,刚好可以覆盖3个二进制位

袁小进想,原来,八进制出现的目的,仅仅是为了书写的简洁

再一想,Linux操作系统上设置文件的权限不就是这样做的吗?

Linux系统上有很多文件,每个文件针对不同的用户有不同的权限,权限分为可读、可写、可运行,刚好三个方面

于是,聪明的系统开发者,为了最大程度的节约空间,只使用了3个二进制位来表达某个文件对某个用户的权限:

对用户张大强LOL.exe文件的权限是101,表示张大强对文件LOL.exe拥有读取和运行权限,但不能修改

对用户李旺财葬爱家族族谱.txt文件的权限是111,表示李旺财同学对文件葬爱家族族谱.txt拥有所有权限

但每次给不同用户赋予权限总是显得比较麻烦,显然不符合程序员高贵的气质

于是,程序员们往往使用一个八进制的数字来表达某个文件对某个用户的权限

于是有了下面的Linux命令

shell
# chmod 是命令,表达要重新赋予权限
# 文件《葬爱家族族谱.txt》,针对三种用户(所有者、所有组、其他人)分别赋予权限7、6、2
chmod 762 葬爱家族族谱.txt

虽然袁小进同学还没有彻底搞清楚所有者、所有组、其他人是什么意思,但他终于明白了原来762就是一个三位的八进制数,每个八进制代表一种用户权限,这样书写,比使用9位的二进制书写更加简洁

所以,总结出来:八进制数没有实质意义,仅仅在某些场景中的一种简化书写方式,计算机内部仍然、永远使用的是二进制的方式存储

但是,另一个问题出现了。

如果书写二进制,虽然写的比较麻烦,但是我写起来脑袋清楚啊,而我写八进制,总是要掰指头换算一次,太麻烦了。

不过,袁小进仔细思考了一下,发现并不麻烦

之前在学习二进制和十进制相互转换时有一种简便方式,即8421对照码

8421对照码适用于4位的二进制,对于3位的二进制,421码不是就足够了吗?

于是有了下面的简单算法:

101 = 421101 = 4 + 1 = 5

111 = 421111 = 4 + 2 + 1 = 7

011 = 421011 = 2 + 1 = 3

同样的方式,反向拆分也是可以的:

5 = 4 + 1 = 421101 = 101

7 = 4 + 2 + 1 = 421111 = 111

3 = 2 + 1 = 421011 = 011

想到这里,袁小进同学露出了满意的微笑。它在额头画上一个圈圈,高高兴兴的回家过年了......