搜索 K
Appearance
博客正在加载中...
Appearance
除了十进制,世界上还有很多进制。
理解进制,有助于我们学习基础数学;进制也是理解计算机的基础。
文明萌芽之前,人类的祖先还没有「数」的概念。
然而人类终究是要和数字打交道的 —— 除了每天的吃喝拉撒,祖先们渐渐需要面对「打到了多少猎物」、「部落有多少人口」这类简单的统计问题。他们开始动用身上的各种部位(例如手指与脚趾)来计数,后面还发展到用石子、结绳来计数(推荐阅读:计算机简史 - 手动计算时代)
假定某个人有 4 只猫,他可能画 4 只猫作为记录。

但如果每增加一只就画一只,可能太麻烦了;我们能不能用一条竖线来表示呢?可以的,例如:| | | | 表示 4 只猫
但如果有 27 只猫,用画 27 个竖线来表示数量就显得很麻烦了:| | | | | | | | | | | | | | | | | | | | | | | | |
而且也很不直观,不能一眼看出数量,还得自己去一个个数。
于是,古人们想到得有一种更好的办法才行,进制就这样诞生了。
什么是进制?两个要点:
此时, 一个数字不仅表示数量,它的位置也很重要。严谨地说,数字的位置更重要,100 和 1000000 中都只有一个 1,但我们知道一百万比一百要大得多。
如今,我们常用阿拉伯数字来表示数量。例如一辆车我们用 1 表示,两辆车我们用 2 表示。
但其实,0~10 这十个数字,都是符号而已。符号不仅仅可以用于表示数量,也可表示事物。例如我们说“3 号选手”, 这里的 3 就是指某个人;又例如 2022 年 3 月 19 号,这里的 3 指的是 3 月。
有没其他符号可以表示 ”数量 2“ 这个概念呢? 有的,在罗马数字中,1~20 分别为:Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ、Ⅺ、Ⅻ、XIII、XIV、XV、XVI、XVII、XVIII、XIX、XX。
也就是说,对于数量的表示而言,我们用什么符号都是可以的(阿拉伯数字、罗马数字),只要人们能理解就行。比如完全可以约定,J 是 11,Q 是 12, K 是 13(扑克牌)。
在国内,对数字的表示也可以用中文,例如壹贰叁肆伍陆柒捌玖,在一些正式场合中会用到。
在法国,不同数字的表示如下:

法语数字单词表
如果各国都采用各自的数字系统,那么国家之间的沟通是很困难的。例如我们可能看不懂法国的单词表,法国人也看不懂我们的壹贰叁肆伍陆柒捌玖。
为了方便,目前国际间统一将阿拉伯数字用于交流。在全世界大部分范围内,阿拉伯数字都是被人们所知道的。
也就是说,阿拉伯数字是一种标准。标准的好处在于,全世界的人都知道,不用担心引起误解。比如在罗马数字中,Ⅹ 代表数字 10,但如果不事先说明这是罗马数字,人们也可能认为这是一个英文字母 X。
数字并不仅仅用于做计算。例如:
理解了符号与数量,接下来我们讲讲进制。
十进制,英文为 Decimal System,常缩写 Dec 或 D。
十进制也是我们日常在用的进制,这里快速过一下。
十进制中,不同位置的数字,代表的值是不一样的:
上式中,每个 1 代表的含义是不一样的,每左移一位,数值就大 10 倍(也可以理解为乘以 10)。
也就是说,每个 1 的乘数是不同的。乘数也可以理解为权重(权值):
每一个数位上的权重如图:

所以上式也可以写成:
注意,小数部分也是这样,只不过数值小了 10 倍(可以理解为除以 10)是 10 的 负 N 次方:
0.75 = 7×10-1 + 5×10-2
在十进制中,十也称为基数。
其实我们日常生活中已经用到不少进制了:
八进制,英文为 Octal,常缩写为 O 或者 o
如果,如果人类像卡通人物那样,每只手上只有 4 个手指会怎样呢?我们可能就不是用十进制,而是八进制。当要表示超过 “八”这个数量时,我们需要进位,逢八进一。例如:
| 要表示的数量 | 符号 |
|---|---|
| 一 | 1 |
| 二 | 2 |
| 三 | 3 |
| .... | ... |
| 七 | 7 |
| 八 | 10 |
也就是说,在八进制中,10 表示的数量是 “八”。
第一次接触这种概念,可能会有点蒙,但不用担心,继续往下看多几种进制,就会有点理解了。
为了方便说明一个数用的是什么进制,我们可以用括号将数字包住,并且用数字下标表明这是几进制,例如八进制的 12 可以表示为 (12)8
在八进制里,每个数的乘数是 8 的 N 次方。每左移一位,数值就大 8 倍(也可以理解为乘以 8):
除了十进制,还有十六进制、八进制和二进制等等常用的进制。
虽然每种进制的基数不同,但进位规则、加减乘除等运算是一样的。
二进制,英文为 Binary,常缩写为 B 或 b
二进制是最简单的进制系统了,逢二进一,也是计算机中采用的进制。可以说,计算机只认识二进制,只处理二进制,像我们看到的文本、图像、视频、各种软件等等,最终都是转化为二进制让计算机处理。
| 要表示的数量 | 符号 |
|---|---|
| 一 | 1 |
| 二 | 10 |
| 三 | 11 |
| 四 | 100 |
| .... | ... |
| 七 | 111 |
| 八 | 1000 |
例如 (111)2 中,每位数的乘数也不一样了,每个乘数是右侧乘数的两倍。
(111)2 = (1×22 + 1×21 + 1×20)10 = (7)10
每一个数位上的权重如图:

当二进制的位数很多时,一连串看起来有点头皮发麻,所以一般每隔 4 为就用一个空格分割。
同理,十进制也有这样的习惯,例如每隔 3 位用逗号分割,这叫三位分节法,例如 1,000,000
在看多一个例子,(1011 0110)2 =1x27 + 0x26 + 1x5 + 1x24 +0x83 + 1x22 + 1x21 + 0x20 = (182)10
示意图:

二进制的加减乘除例子:

从上面的例子中可以看到二进制算术运算的两个特点:
如果我们再能设法将减法操作转化为某种形式的加法操作,那么加、减、乘、除运算就全部可以用“移位”和“相加”两种操作实现了(下一篇文章会讲)。
利用上述特点能使运算电路的结构大为简化,这也是数字电路中普遍采用二进制算术运算的重要原因之一。
十六进制,英文为 Hexadecimal,常缩写为 X。
如果说要用超过十进制的进制,例如十六进制,需要一个单独符号来代表 “十” 这个概念,人们常用字母来表示:
| 要表示的数量 | 符号 |
|---|---|
| 一 | 1 |
| 二 | 2 |
| 三 | 3 |
| 四 | 4 |
| 五 | 5 |
| 六 | 6 |
| 七 | 7 |
| 八 | 8 |
| 九 | 9 |
| 十 | A |
| 十一 | B |
| 十二 | C |
| 十三 | D |
| 十四 | E |
| 十五 | F |
| 十六 | G |
(10)16 =(16)10, (A)16 = (10)10
每一个数位上的权重如图:

| 十进制 | 二进制 | 八进制 | 十六进制 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
| 2 | 10 | 2 | 2 |
| 3 | 11 | 3 | 3 |
| 4 | 100 | 4 | 4 |
| 5 | 101 | 5 | 5 |
| 6 | 110 | 6 | 6 |
| 7 | 111 | 7 | 7 |
| 8 | 1000 | 10 | 8 |
| 9 | 1001 | 11 | 9 |
| 10 | 1010 | 12 | A |
| 11 | 1011 | 13 | B |
| 12 | 1100 | 14 | C |
| 13 | 1101 | 15 | D |
| 14 | 1110 | 16 | E |
| 15 | 1111 | 17 | F |
除了用数字下标表示是几进制外,还可以有这样的表示方法:给数字加个前缀,取自各进制的英文首字母(大小写均可):
| 进制基数(radix) | 前缀 | 示例 |
|---|---|---|
| 二进制 binary | 0b,0B | 0b11 = 2+1=3 |
| 八进制 octal | 0o,0O | 0o11 = 8+1=9 |
| 十进制 decimal | 无前缀 | 11 = 11 |
| 十六进制 hex | 0x,0X | 0x11 |
由于多种进制的存在,它们之间的相互转换是经常会遇到的事情。
二进制转十进制:只需将每位数乘以对应的乘数,再将结果相加即可。
例如 (1011.01)2 = 1×23 + 0×22 + 1×21 + 0×2-1 + 1×2-2 = (11.25)10
十进制转二进制:采用 “除 2 取余,逆序排列”法:
首先用 2 整除一个十进制整数,得到一个商和余数
然后再用 2 去除得到的商,又会得到一个商和余数
重复操作,一直到商为小于 1 时为止
然后将得到的所有余数全部排列起来,再将它反过来(逆序排列)
举例:将 (173) 转为二进制过程如下

原理是什么呢? 我们自己可以推理下。
前面我们知道二进制数转十进制数是怎么转换的:
小数转二进制:采用"乘 2 取整,顺序排列"法:
用 2 乘十进制小数,可以得到积,将积的整数部分取出
再用 2 乘余下的小数部分,又得到一个积,再将积的整数部分取出
重复操作,直到积中的小数部分为零,此时 0 或 1 为二进制的最后一位,或者达到所要求的精度为止
例如,将 0.125 转换为二进制,步骤如下:
0.125 * 2 = 0.25 ------0
0.25 * 2 = 0.5 ------0
0.5 * 2 = 1.0 ------1
当小数部分为 0 就可以停止乘 2 了,然后正序排序就构成了二进制的小数部分:0.001
其原理,和十进制转二进制的原理一样。
特别注意,不是所有的十进制数都能转化为有限位二进制数的。举个例子,十进制小数 0.7,转化为二进制小数是:0.1011001100110......,是无限循环小数,循环节是 0110。
那些能分解为以 (1/2)n 为单位的十进制小数,才可以转化为有限位数的二进制小数。
如十进制数:13/16=0.8125,它可以是拆成:13/16=1/2+1/4+1/16,或者直接可以看作是 13 个 1/16 所组成。而 1/2,1/4,1/16 这些数都是符合 (1/2)n 形式的数。
如果又有整数又有小数:将整数部分和小数部分先单独转为二进制,再合在一起就可以了。
由于 4 位二进制数恰好有 16 个状态,而把这 4 位二进制数看作一个整体时,它的进位输出又正好是逢十六进一,所以只要从低位到高位,将整数部分每 4 位二进制数分为一组,并代之以等值的十六进制数。
例如,将二进制数(0101 1110.1011 0010)化为十六进制数:

若二进制数整数部分最高一组不足 4 位时,用 0 补足 4 位:小数部分最低一组不足 4 位时,也需用 0 补足 4 位。
十六进制转二进制,只需反过来,每一位十六进制数用等值的 4 位二进制数代替就行。例如,将 (8FA.C6) 转为二进制:

与十六进制和二进制,互相转换基本一样。
在将二进制数转换为八进制数时,只要将二进制数的整数部分,从低位到高位每 3 位分为一组,并代之以等值的八进制数,同时将小数部分从高位到低位每 3 位分为一组并代之以等值的八进制数就可以了。
二进制数最高一组不足 3 位或小数部分最低一组不足 3 位时,仍需以 0 补足 3 位。
例如,若将二进制数 (011110.010111) 化为八进制数:

反之,若将八进制数转换为二进制数,则只要将八进制数的每一位代之以等值的 3 位二进制数即可。例如,将 (52.43) 转换为二进制数时,得到:

8 进制转 10 进制、16 进制转 10 进制:就只能按权重展开后,相加得到十进制了。
10 进制转 8 进制、10 进制转 16 进制,可以先转为 2 进制,再分组转换。
如果我们已经知道如何转换进制了,当数字很大的时候,自己转换就是浪费时间,并且容易出错,因此,我们可以借住计算机帮助我们转换。
Win10 自带一个计算器,可以通过按下快捷键 Win + R,输入 calc 并回车打开。
在菜单栏里选择程序员:

手动实现各进制下的转换
自行实现在各进制下的加减乘除
用计数器验证结果