说到数的进位制,生活中的我们脑海里马上闪现的往往是“十进制”,但是在“计算机编码|二进制”中我们讲了现代计算机系统中采用的二进制数据表示法。
还有哪些进制
对于普通使用计算机的用户来说,二进制是几乎感知不到的,我们看到的使用的数据基本上还是十进制的,计算机要处理这些数据时,会自行转换为二进制后再进行处理。但是在编程时,就不一样了,我们有时候会需要感知数据位的多少,或者数据一些位的特征:
比如:当我们看到一个字符码如果最高位为1,就可以知道这个字符肯定不是标准的ASCII编码了;
再比如我们想知道12345这个数据需要多少字节来保存,用十进制我们很直观地看出来,但是如果用二进制表达为11 00000011 1001,我们马上就知道是14位,所以至少需要两个字节;
再比如在“电子显示|RGB”,我们知道用RGB数据是一个24位数据,用二进制表达我们可以很清楚分解出R、G、B的数据,每个数据8位即一个字节。
也就是说我们有时还是需要用二进制来表达数据,但是用二进制表示数据有一个最明显的弊端——过长的数字代码,比如十进制的1024,用二进制表示为11 1111 1111,需要10位数字;再比如上面说到的12345,需要14位等等。过长的数字代码,对于我们阅读或书写都会有一定困扰。
为了解决这个问题,所以有了八进制、十六进制。八进制,顾名思义,就是逢八进一,十六进制则是逢十六进一了。那为什么是八进制和十六进制,而不是九进制、十二进制之类的呢?这是因为2、8、16,分别是2的1次方,3次方,4次方。这一点使得三种进制之间可以非常直接地互相转换。八进制或十六进制缩短了数字代码的长度,但保持了二进制数的表达特点。为什么这样说?通过下面进制转换中的描述便可知晓。
八进制、十六进制
每个进制都需要对应的符号来表达数据,比如十进制用0~9共十个符号来表达数据,而二进制用0和1两个符号表达数据。那么八进制,我们大概也猜到了,是用0~7共八个符号来表达数据,十进制里的数字8,在八进制里表达为10。而十六进制的16个符号为:
0~9共10个符号 + A~F(大小写都可用)共6个符号
在十六进制里,A~F分别对应十进制中的10~15,对应关系如下表:
十六进制 | 十进制 | 十六进制 | 十进制 | |
0 | 0 | 8 | 8 | |
1 | 1 | 9 | 9 | |
2 | 2 | A | 10 | |
3 | 3 | B | 11 | |
4 | 4 | C | 12 | |
5 | 5 | D | 13 | |
6 | 6 | E | 14 | |
7 | 7 | F | 15 |
进制的数据表达
我们在编程时,需要表达一个数据的时候,怎么来区分这个数据倒底是什么进制的呢?如果说一个数据里有A~F这样的符号,比如1F2A这样的数据,我们基本可以识别出来是十六进制的,但是如果是“10”这样的数据,这个数据倒底是什么进制的数据呢?
为了解决这个问题,编程语言会约定针对不同进制的数据用不同的标识来进行区分,大部分编程语言规定了用0x打头表示的是十六进制,0打头的表示是八进制。如下表:
10 | 无任何标识表示十进制的10 |
010 | 表示的是八进制的10,对应十进制的8 |
0x10 | 表示的是十六进制的10,对应十进制的16 |
0b10 | 表示的是二进制的10,对应十进制的2 |
从上表中我们可以得知,0打头的数据是表示八进制,这与生活中有不同,生活中我们在数字前面添0不改变数字大小,但是在程序里要是在一个十进制数据前添了0,计算机就会将其当作八进制数据处理了。
那为什么都是0打头来标识,而不用"h"、“o"、”b“这几进制的首字母之类的来标识呢?这是因为几乎所有编程语言都规定了,代码中变量的首字母不能是数字,所以进制标识用0打头,计算机就知道这不是变量,而是一个数据,而用字母打头来标识,会让计算机无法区分这倒底是个数据还是个变量。
进制转换
在讲二进制和八进制、十六进制之间的转换前,我们必须先讲一讲二进制与十进制之间的转换。
二进制与十进制的转换
在“计算机编码|二进制”篇里我们知道了二进制逢二进一,十进制的0~15对应的二进制如下:
十进制 | 二进制 | 十进制 | 二进制 | |
0 | 0 | 8 | 1000 | |
1 | 1 | 9 | 1001 | |
2 | 10 | 10 | 1010 | |
3 | 11 | 11 | 1011 | |
4 | 100 | 12 | 1100 | |
5 | 101 | 13 | 1101 | |
6 | 110 | 14 | 1110 | |
7 | 111 | 15 | 1111 |
这个转换也可以通过计算得到,下面稍简单介绍一下,如需要了解更多,请自行搜索了解。二进制数据中由低到高每一位其权值分别为20,21,22……2N,即像1111这个二进制数据,可以通过以下计算得到其十进制值:
1*20+1*21+1*22+1*23= 15
如果为1101,计算如下:
1*20+0*21+1*22+1*23= 13
(由低到高第二位为0,所以权重前系数为0)
二进制转换为十进制,通过权重和其对应位数据乘积后相加得到;十进制转换为二进制则是通过不断除2得到的余数组合而成。
二、八、十六进制的转换
二进制数转换为十六进制,由于24=16,所以我们只要将二进制数据以4位一段,分别转换为十六进制即可,如下:
二进制数据: 1111 1101
以四位一段得到的十进制: 15 13
对应的十六进制数据为: F D
那反过来十六进制怎么转换为二进制呢?如F7对应的二进制:
先转换F:看到F,我们知道对应的十进制是15,而十进制的15对应的二进制为1111;
再转换7:7的二进制为111,不足四位,前面添0补足四位为0111;
所以F7的二进制为1111 0111。
八进制的使用并不多,它的转换与十六进制基本一样,无非一个是四位一段,一个是三位一段,所以在此不再细述了。
如上即为计算机系统中各类数据的进制表达。我们已经知道了计算机系统中不管是字母、符号,还是数字,都是用二进制来表达的,但二进制表达的数据不利用人类阅读和书写,因此就有了八进制、十六进制。用二进制表达数据,上面我们提到的都是以正整数来示例,那么在计算机中负数是如何来表示的呢?且看下篇:计算机编码|原码、反码、补码。
往期文章
● 1. 电子显示|点阵(像素)
● 2. 电子显示|RGB
● 3. 电子显示|颜色空间
● 4. 电子显示|YUV
● 5. 电子显示|视频显示
● 1. 计算机编码|二进制
● 2. 计算机编码|ASCII编码
● 3. 计算机编码|各类字符编码