其实现在我们就已经在学习计算机的路上了,只不过我们需要首先普及一些更为通用的知识。
这一章我们先来讲一下进制和编码。
进制
什么是进制
进制是计算机当中最基础的一个概念,一般来说这个概念会在高中接触(如果接触过数学奥赛的话可能会在初中前后接触),它描述的是一种计数方法。
一般我们说一个数是R进制,我们会定义这样几个事情:
进位机制(基数):逢R进一,借一当R;同时,它规定了在这个计数方法当中每个位最多可能出现哪些数字。
位权机制:这个可以简单类比为个十百千万,描述的是一个数字在不同位时所对应的大小(举个例子就是6在个位和十位表示的值是不一样的)。
计算机当中核心的进制有两种:十进制(面向人类)和二进制(面向机器)。二进制的定义是:逢二进一,每位只有0和1两个数值;位权以2为底,每向前移动一位所表示的大小就乘二。比如:(0001)bin=(1)dec,而(0010)bin=(2)dec。
由于二进制需要把0和1全部展开,过于麻烦,因此人们在二进制的基础上提出了八进制、十六进制,这些进制和十进制的计算方式类似,八进制是逢八进一,十六进制是逢十六进一(不理解十六进制的可以去看看中药铺的十六两称或者比较老的杆秤)。
如何进行二进制和十进制的转换
二进制转到十进制,只需要做乘法就行,比如:(0100 1001)bin=1*2^0+0*2^1+0*2^2+1*2^3+0*2^4+0*2^5+1*2^6+0*2^7=(73)dec。小数同样如此,只不过这时的位权会变成0.5,0.25,0.125等1/(2^n)。
十进制转二进制会有一点复杂。对于整数部分,我们可以直接用长除法,将十进制的数x连续地除以2直到最终剩下0或者1,然后从最后的结果向前不断取余数,最后读出来的就是二进制的整数;对于小数部分,我们则需要采用乘法,不断地乘2并取走整数部分(每次都只保留小数部分),最终将取走的整数部分从前到后串联起来就是二进制的小数。值得注意的是,有些十进制小数在二进制下可能会出现算不尽的情况,这就会导致一些舍入引发的问题,比如经典的0.1+0.2!=0.3。
编码
计算机当中所有信息都只能用二进制表示,因此我们不得不找到一种将现实当中的信息用二进制表示的方法。最易于处理的是整数,或者说是定点数,所以接下来我们用整数来举例子。
整数的表示方法一般有三种,原码、补码和移码(反码使用的极少所以我们这里不作表述)。
原码就是将整数的绝对值转换到二进制,然后在最前面补上一个符号(现在的计算机标准当中用0表示正,1表示负)。这种方法的好处是转换方便,但是坏处是计算复杂,需要首先判断符号位和运算,然后再计算绝对值,最后还要重新计算符号位。
移码是给数字加上一个基础值,把负数也变成正数。这样的好处是负数和正数的表示方式是统一的,可以直接进行加减法运算,但是坏处是零点在移码过程中会动,如果需要一些特殊的计算这样也会出问题。
补码的操作方法是让负数和绝对值相反再加上1,这样可以让负数和正数统一一种表示方式。这种方法虽然在转换上比较麻烦,但是在计算时很简洁,可以直接运算(符号位可以当作数字的一部分参与运算)。实际在工程中,我们并不会采用刚才所说的先取反再加一的方法,因为我们可以用一个更简单的方法:对于原码为x的数,其补码为2^n sign(x) |x|,因为移码通常是将整数的零值移动到负数下限的位置,而补码可以看作将整数的零值移动到负数下限的位置之后又转了一圈移动回来。