一、什么是计算机?
一种能够按照事先存储的程序,自动、高速的对数据进行输入、处理、输出和存储的系统。
如果要进行数据的输入,即将要处理的数据进行输入,常见的输入设备有:键盘、鼠标。对输入的数据做计算就是处理,比如解一个一元二次方程。输出就是将处理好的数据输出出来,最常见的输出方法就是将数据输出到屏幕上,也可以输出到文件里面,或者其他的输出设备,比如音箱。必要的信息我们也要进行存储,存储好的东西,比如买东西,其实就是从数据库里面来查询的。
计算机包括软件和硬件两大部分
二、计算机的发展历程
电子管:其结构与老式的灯泡类似,玻璃管道内部是真空,封装了若干个电极,这种状态的设计,容易因为电压不稳等原因而烧坏;电子管是十进制方式运算,用十种不同的电流表示十种状态,这样的设计同时也是个弊端,那就是当计算机运行时,假如周围有着一台另外的电器比如微波炉在工作,计算机的信号就容易被干扰而出现错误。同时,计算机的运行需要成千上万个电子管的同时运行,所以机器是很大的。ENIAC是世界上第一台计算机,非常庞大,就是使用了电子管。
晶体管,只有两个状态:1态和0态,也即截止和导通两个状态。此时的计算机开始变成二进制的了,是固体状态,采用半导体,因此没有电子管那么容易损坏,常见的晶体管如三极管,发光二极管等。
集成电路:只是将晶体管的体型通过技术缩小了,将很多的晶体管集成在一个电路上
大规模集成电路和超大规模集成电路(CPU)
三、逻辑运算
那么我们的计算机是如何实现将信息传入呢?答案是通过将两种状态的电流表示两个数字的,然后通过数字的重组实现更多的编码状态,然后将这样的状态再来表示我们信息的单位,成千上万个信息单位组成了我们社会的一条条信息。所以信息的本质就是一个个的0和1。
计算机,其用途与其名称相同,就是用来计算的。但是这样的数字电路不像传统的机器,不能像算盘那样的机器进行运算,现代计算机实现计算的方式是逻辑运算集合。那么什么是逻辑运算呢?
逻辑运算是数字电路的基础,而数字电路又是几乎所有现代软硬件的基础
1.布尔代数
英国数学家乔治·布尔在1847和1854年提出的数学模型,起源于数学领域,是一个用于集合运算和逻辑运算的公式<A、 ┐ 、 ∧ 、∨ >。其中A为一个非空集合。 ∧ ∨ 为定义在A上的两个二元运算(二元运算指的是面向两个元素进行运算), ┐ 为定义在A上的一个一元运算(一元指的是面向一个元素进行)
就像y=ax+b定义在集合A上的关于x和y的一个运算一样,逻辑运算也定义在A上,对相关元素进行处理,而处理一元二次方程的解方程过程对应过来就是对相关元素进行与或非的逻辑运算的集合。
┐为非 NOT
∧为与 AND
∨为或 OR
位于A内的布尔运算值只能有两个,一个是真(用1表示),一个是假(用0表示)。我们通常说非0即1,非1即0,可以用高电压表示0,用低电流表示1,这就实现了拿数字的0和1和电压的高和低带上关系了。
上面提到的布尔运算有:逻辑与,逻辑或,逻辑非,异或和同或等等。
2.布尔运算(与、或、非)
(上面的图片是晶体管,我们先不管其内部结构,重在理解其联系电流与逻辑运算的过程)
我们只看第一个图片最基础的结构
这个晶体管和我们所经常听到的三极管的运作方式原理是相同的,他通常有两个状态,即导通与截止。
c端为输入端,我们通常是输入或不输入电流,用1表示输入电流,用0表示不输入电流。而中间b端所连接的片状物,我们只要知道他是半导体就可以了。他的作用是当b端输入电流时,可以控制c的电流通过半导体到达e,我们就可以得到一个信号为1;而当b端不输入电流时,半导体就不能导通,反而会截止,e端接受不到电流,我们得到的信号为0。
知道了其工作原理,我们来看下面这张图,可以直观地帮助大家理解与运算是怎么一回事。
与运算:也即逻辑乘(可以理解为结果是两个布尔值相乘),是一个并且(&&)的关系。只有两个都成立为1时才成立,若有一个不成立为0,结果将不成立为0(只有A真B也真时才真)
我们将两个晶体管串联,我们在左端给一个current(电流),有两个电流的输入端
当两者都输入电流时,这个电路才会通路,如果有其中一个输入端input是没有电流输入的,那么输出端output将不会有电流。我们将输入端和输出端的有无电流情况记为:有电流为1,无电流为0
我们也可以将两个晶体管串联的情况看作是两个开关,因为这个晶体管的工作方式就相当于是个控制端。将开关闭合记为1,开关断开记为0,有电流记为1,无电流记为0。
只有当两个都为1都为真时,结果才为真为1。有一个为0为假时结果即为假为0
将所有的情况结合起来就可以得到一个这样的表格,我们称之为逻辑真值表
最后一图为与运算的国际符号
或运算:也即逻辑加(可以理解为结果为两个布尔值相加);是一个或者(||)的关系。只要两个中有一个成立为1时结果就成立为1,只有两个都不成立为0时结果才不成立为0(只要A或者B有一个为真就为真,只要有一个为真时,结果必然为真,当两个都为假时,结果才是假。)
与前面的那张图想法相同,不过不同的是,这次我将所有的开关或者是晶体管并联了。
同样的给一个电流,这次只要我们有一个开关或者是晶体管通电为真为1时,结果就是为真为1,只有当两个都不通电为假为0时,结果才为假。
逻辑真值表和国际符号如上图。
非逻辑:
争对于一个元素的运算,是逻辑门电路里最简单的运算,我们就不细讲了。
将开关按下为1,打开为0,灯亮为1,灯不亮为0,那么想要灯亮,开关必然是打开的,如果开关闭合了,那么灯必然不亮。
也即非0即1,非1即0
3.用与或非门电路实现异或
异或:XOR
其逻辑真值表是相同出0,不同出1。
可以依照电路示意图分析出他的真值表
计算机的硬件基础是逻辑电路,逻辑电路通常有两种状态:即通、断,这两种状态正好可以表示二进制的0,1——位(在计算机中,也可以将电压的高和低分别代表1和0)
这两种状态是非常稳定的,因为没有那么多的状态,信号不会被各种同样带有晶体管的电器所干扰,使得计算机的工作更加稳定,不会那么容易发生错误。所以二进制的特点就是比较稳定。
位的0和1只是形式,在不同的应用中有着不同的含义。
四、二进制与R进制
1.引入二进制
逻辑运算能够实现与或非的三种基本运算,但是如果我们要想让计算机实现加减乘除等最简单的运算,仅仅有这三个运算时不行的,我们会将成千上万个逻辑电路结合来实现,这样我们的运算问题就解决了,但是又有一个新的问题摆在我们面前。
那就是数字的问题,要知道,我们只有两个状态和数字,怎么能够实现现实中遇到的大于二的数字的运算呢,这就引入了二进制的方法,就是像十进制那样逢2进1。
一个二进制值可以表示一个数,我们可以把真和假当作1和0,如果想表示更多东西,加位数就行了,和我们所熟悉的十进制一样,一位十进制数能表示的数字只有0-9十个数字,如果想要表示更大的数字,加位数就行了。
2.进位计数数制
那么进位计数制是怎么运行的呢,你真的了解十进制吗?
基数:十进制为10,二进制为2,R进制为R
权:某一进制中各位1所表示的值为该位的权(比如十进制中个位的权值为1,十位为10,百位为100,千位为1000……),也即基数的从0次方开始一直加,10^0,10^1,10^2,10^3……
在研究二进制之前,我们先来研究一下我们所熟知的十进制:拿一个只能计数不能运算的算盘举例
十进制中,只有0-9十个数字,但是想要表示更多位数的数字,我们也是用了进位制的方法。把最左面一列当作个位,然后珠子当作1-9,想要表示0就是珠子都在下方。当所要表示的数字等于十时,就将此时所有的个位珠子推到最下面,表示个位为0,将十位的珠子向上推一个,表示十位为1,这样我们就可以拿这样的状态表示了10。如果想要表示11,在10的基础上将个位的珠子向上推一个,表示个位为1。
这样我们就发现了这样的规律:个位要表示的数字就是个位的数字再乘以1(也即10的零次方),十位要表示的数字就是十位的数字再乘以10(10的一次方),百位要表示的数就是百位的数字再乘以100(也即10的二次方),R位(第n位)要表示的数字就是R位的数字再乘以10的(n-1)次方(该位的权重)。
在十进制中,10就是十进制的基数,而每一位(n)的数字所乘的10的(n-1)次方为该位的权,这就是进制数的奥秘。
拿263举例,在十进制中就是2个100,6个10,3个1,加在一起,就是263,每列有不同的乘数,每个乘数都比右边大10倍,因为第一列有十个可能的数字(0-9),但是到了十位就是10*10个可能的数字,因为个位每满10要向十位进一个数字,但是个位和十位是不同的,所以需要将他们加起来,就能够加出此时的数字。
接下来看二进制:
3=1*2的一次方+1*2的零次方=(11)2
虽然个位有两个状态,十位也有两个状态,但是11并不代表4,而是3,因为0也是二进制的一个数,二进制和十进制一样, 都是从0开始的。
10=1*2的三次方+0*2的二次方+1*2的一次方+0*2的零次方=(1010)2
二进制中的0就是0,和十进制中的0是相同的,用二进制表示从0到10:
0 1 10 11 100 101 110 111 1000 1001 1010一定要记得,当所有的位上都是1时,此时才会加成1000……的状态,像十进制一样,当所有位都加满时,最高位才会加1(110后面不应该是1000,而是接着加个位的数字;而且往上加时,总是加成1,而非0,因为最高位本来就是0,只是不显示而已,继续加时,就会变成1)
拿二进制数10110111举例:十进制中的1 10 100 1000 10000……变成了1 2 4 8 16 32 64 128……
10110111是1个128,1个32,1个16,1个4,1个2,1个1的加和组成。所以10110111对应的十进制数就是183。
3.二进制数的加运算纸上方法
二进制数的加运算:
以十进制数为例,183+19是9+3=12,个位为2,向十位进1,十位8加1加1为十,因此十位为0,向百位进1,百位为1加1为2,得到202
二进制也一样,183+19相当于是二进制中的10110111加上10011,而10011前面可以默默补上0,因此就变成的10110111加上00010011:从个位开始,1加1为2,2对应的二进制是10,因此向上一位进1,个位为0(二进制中的数字是满2进1,但并不代表就有2,而且二进制中的第三位数字是2,而非3,他是从0开始的,所以不要以为单单一个数字1就能够代表十进制中的2,因此在二进制中,每满2,就要往前进1,而不是0,因为0就代表0,二进制中进的都是1而没有0)第二位为1+1+1,所以得数为3,在二进制中,3是11,所以第二位为1,向下一位进1……以此类推,得数为11001010
五、进制转换
我们引入了二进制,但是我们人用的还是二进制,那么就必须让计算计给我们输入的十进制数据转换成二进制供计算机计算使用。
1.二进制与十进制
十进制转二进制:
整数部分:除二倒取余
利用十进制数除二取余,得数再除二取余,直到得数为0为止(1/2=0……1),然后从下向上取余数值就是整数部分的值,这整数部分方法谓之除二倒取余
小数部分:乘二正取整
对小数部分乘二,当满一时,记下整数部分为1,乘了二还是不满一时,记下整数部分为0,一直乘,能乘到正好变成整数1时(0.5*2=0……1),最好,如果乘不成1,那就乘到要求的保留位数就好。然后从上向下取整数部分记下的值,即为小数部分对应的二进制,此方法谓之乘二正取整
二进制转十进制:
二进制转十进制是利用按权相加法,即每一位的数字乘以对应的权值然后相加即可的到十进制的对应数值。
小数部分同样是乘以2的对应次数,比如第一位小数就是乘以2的负1次方……
2.R进制与十进制
我们借鉴二进制与十进制的方法:
十进制转R进制:
算十进制与别的进制转换,十进制转R进制,就是除R倒取余和乘R正取整的方法有(太麻烦,如果是十进制转十六进制还得一直除以十六,不好算)
十进制转R进制还有一种方法就是十进制先转为二进制,再二转R进制(建议用这个)
R进制转十进制:
R进制转十进制,只有一种方法就是按权相加法,当然,此时的权就是对应的R的各个位上的权了
3.R进制与二进制
二进制转R进制:
图片左两行为二进制与十进制,右边两行为二进制与十六进制
注意:通常用数字0、1、2、3、4、5、6、7、8、9和字母A、B、C、D、E、F(a、b、c、d、e、f)表示,其中:A~F表示10~15,这些称作十六进制数字。
几进制的最高数字不是进制数字本身,而是比进制数字正好小1,这是因为还有一个数字0
二进制转八进制:从小数点位置起向左右两边划分,每三个为一组,不足三个的在最左边或最右边添0补齐,然后对照上面的表算出这一个单元对应的八进制数字是多少,写上就可以,比如:1011010.100101=001 011 010.100 101=132.45(8)
二进制转十六进制:从小数点位置起向左右两边划分,每四个为一组,不足四个的在最左或最右添0补齐,对照上边的表进行计算,算出一个单元的数字然后正序排列写出来,比如:1011010.100101=0101 1010.1001 0100=5A.94(16)
但是这种划分区间的有一个弊端就是只能算二的整数次方的进制,如果碰见了别的如二进制转化为五进制,就先转化为十进制,在除R倒取余,乘R正取整来求五进制。
如果本身是十进制转五进制,那就不要转二进制了,直接除R倒取余,乘R正取整。
要想算别的没有二进制和十进制的数字之间的转换(比如四进制和五进制),就需要先将其转换为二进制或十进制,然后以二进制或十进制为中间值来转换。
R进制转二进制:
R进制转二进制除了按权相加法变为十进制再转二进制别的方法:
八进制转二进制:与“二进制转八进制”转换方法相反:132.45(8)=001 011 010.100 101=1011010.100101(2),将每一位数字转换乘对应的二进制三位数字,然后正序排列就好
十六进制转二进制:与“二进制转十六进制”转换方法相反,把每个数字对应的二进制写出来,然后正序排列,比如:5A.94(16)=0101 1010.1001 0100=1011010.100101(2)
但是这种方法也仅限于是二的R次幂的进制,别的就不适用了,还是按权相加法更通用
为什么非得是三位和四位:因为8是2的3次方,16是2的4次方
从小数点向两侧扩展既是分区域的方法,又是除R倒取余,乘R正取整的方向所在,这两者的方向是完全一致的。
六、计算机的存储级别
二进制中,一个1或者0叫做一位(bit)
八位能够表示的最小数为0(八位都为0),最大数为255(八位都为1)
因此,八位能够表达256个不同的值,也即2的八次方
如果有n位,则可以存2的n次方个可能值
比如,八位机,八位图像,八位音乐,意思是计算机里面的大部分信息都是八位八位这样处理的,但256个值并不算多,意味着八位游戏只能用256种颜色,八位是如此常见,以至于有着专门的单位来计量:
字节(byte)
一字节=八位
十字节=八十位
千字节kilobytes(kb) 千字节=1000字节
兆字节megabytes(mb) 兆字节=1000千字节=百万字节
千兆字节gigabytes(gb) 千兆字节=1000兆字节=十亿字节
TB=1000千兆字节=一万亿字节
在二进制里,一千字节=2的十次方=1024字节
1000也是千字节的正确单位,1000和1024都对
32位计算机与64位计算机:
意思是一块块处理数据,每块是32位或64位
32位所能表示的最大数据是卡3亿左右(32个1),所以照片会很清晰,他们有上百万种颜色
如果要表示负数:大部分计算机用第一位表示正负,1是负,0是正(不用做任何解释的就是正数),用剩下31位表示数字(能表示的数字范围是负20亿到正20亿左右),虽然是很大的数了,但是还是不够用,所以64位数很有用,64位所能表示的最大数值是9.2*10的18次方
重要的是:计算机必须给内存中每一个位置,做一个标记,这个标记叫位址,目的是为了方便存取数据(如果是64位,内存地址也应该有64位)
七、编码
1.二-十进制代码——BCD码
什么是BCD码?
BCD码的英文全称是Binary-Coded Decimal,简称BCD,按字面解释是二进制十进制代码,是一种二进制的数字编码形式。我们平常用的十进制,每一位分别用二进制来保存,这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。
由于十进制数共有0、1、2、……、9十个数码,因此至少需要4位二进制码来表示1位十进制数。4位二进制码共有2^4=16种码组,在这16种代码中,可以任选10种来表示10个十进制数码,共有N=16!/(16-10)!约等于2.9乘以10的10次方种方案,也即四位二进制码的不同组合可以实现这么多种十进制的数字组合。
BCD码包括8421码,5421码,2421码,余3码等。BCD码可以包括了有权码,无权码这两种。有权码包括了8421码,5421码,2421码。无权码包括了余3码等。
通过改变权值,拥有了不同的编码方式。
2.8421码(BCD码)
指的是四位二进制数,从0000~1001,分别代表十进制数0~9,这十个数每个数都有自己的8421码: 0=0000 1=0001 2=0010 3=0011 4=0100 5=0101 6=0110 7=0111 8=1000 9=1001 ,例如:321的8421码就是 3 2 1 :0011 0010 0001 即: 0011=8x0+4x0+1x2+1x1=3 0010=8x0+4x0+2x1+1x0=2. 0001=8x0+4x0+2x0+1x1=1
其每位的权分别为2的三次方,2的二次方,2的一次方,2的零次方。在这种编码方式中,每一位二值代码的“1”都代表一个固定数值。将每位“1”所代表的二进制数加起来就可以得到它所代表的十进制数字。因为代码中从左至右看每一位“1”分别代表数字“8”“4”“2”“1”,故得名8421码。其中每一位“1”代表的十进制数称为这一位的权。因为每位的权都是固定不变的,所以8421码是恒权码
例:321的8421码就是3 2 1 0011 0010 0001。原因:0011=8x0+4x0+1x2+1x1=3,0010=8x0+4x0+2x1+1x0=2,0001=8x0+4x0+2x0+1x1=1。
3.2421码(BCD码)
一种有权码,从左到右,第一位为1代表2,为0代表0,第二位为1代表4,为0代表0,第三位为1代表2,为0代表0,第四位为1代表1,为0代表0。比如说,1111=2+4+2+1=9,0111=0+4+2+1=7。2421码是一种对9的自补代码,即每一个2421码只要与自身按位取反,便可得到该数按9的补数的2421码,比如4的2421码0100自身取反后就变为了1011,即5的2421码。2421码可以给运算带来方便,因为可以利用·其对9的补数将减法运算转变为加法运算。
4.余3码(BCD码)
余3码是一种无权码,也比较好计算,就是在数字二进制的基础上加上0011,即求出数字8421码后上再加上0011。余3码是由8421BCD码加上0011形成的一种无权码,由于它的每个字符编码比相应的8421码多3,故称为余三码。BCD码的一种。余3码的特点:当两个十进制数的和是10时,相应的二进制编码正好是16,于是可自动产生进位信号,而不需修正。0和9, 1和8,…..5和4的余3码互为反码,这在求对于10的补码很方便。
余三码是一种对9的自补代码,因而可给运算带来方便。其次,在将两个余三码表示的十进制数相加时,能正确产生进位信号,但对“和”必须修正。修正的方法是:如果有进位,则结果加3;如果无进位,则结果减3。
如, (526) 10进制=(0101 0010 0110) 8421BCD码=(1000 0101 1001) 余3码
5.5421码(BCD码)
5421码BCD码各位的权依次为5421,是有权码,其特点是最高位连续5个0后连续5个1。5421码是一种有权码,4位二进制码的权依次为5,4,2,1。从十进制的0~9转换为5421码,就是按照每一位的权凑出所要的数字,比如说9,9=5+4,所以9的5421码就是1100。但是4位二进制码可以表示16个数,十进制中只有10个,就会有6个用不到(不允许出现),这6个分别是0101,0110,0111和1101,1110,1111,这些数字对应的十进制数加起来就超过了9,所以是用不到的。
6.编码文字、图像和声音
除了正数和负数,计算机有时也要处理非整数,比如12.7与1414.2,这些叫浮点数,因为小数点可以在数字间浮动,有好几种方法表示浮点数:最常见的是IEEE 754标准,他用类似科学计数法的方式来存十进制值,例如625.9可以写成0.6259*10^3,这里有两个重要数字,6259是有效位数,3是指数
在32位浮点数中,第一位表示正负,接下来8位存指数,后面23位存有效位数。
文字的表示和存储:计算机用数字来表示字母,最直接的办法是给字母编号,A为1,B为2,C为3,以此类推;著名英国作家,弗朗西斯·培根,曾用5位序列,来编码英文的26个字母
5位,可以存32个可能值(2的5次方),但这个对于26个字母足够了,但是不能够表示标点符号,数字和大小写字母
后来就由于这个需求,出现了ASCII码(美国信息交换标准代码)他是7位,足够存128个不同值,这样就可以表示大小写字母,数字0-9,特殊符号,以及标点符号
二进制 | 十进制 | 十六进制 | 字符/缩写 | 解释 |
00000000 | 0 | 00 | NUL (NULL) | 空字符 |
00000001 | 1 | 01 | SOH (Start Of Headling) | 标题开始 |
00000010 | 2 | 02 | STX (Start Of Text) | 正文开始 |
00000011 | 3 | 03 | ETX (End Of Text) | 正文结束 |
00000100 | 4 | 04 | EOT (End Of Transmission) | 传输结束 |
00000101 | 5 | 05 | ENQ (Enquiry) | 请求 |
00000110 | 6 | 06 | ACK (Acknowledge) | 回应/响应/收到通知 |
00000111 | 7 | 07 | BEL (Bell) | 响铃 |
00001000 | 8 | 08 | BS (Backspace) | 退格 |
00001001 | 9 | 09 | HT (Horizontal Tab) | 水平制表符 |
00001010 | 10 | 0A | LF/NL(Line Feed/New Line) | 换行键 |
00001011 | 11 | 0B | VT (Vertical Tab) | 垂直制表符 |
00001100 | 12 | 0C | FF/NP (Form Feed/New Page) | 换页键 |
00001101 | 13 | 0D | CR (Carriage Return) | 回车键 |
00001110 | 14 | 0E | SO (Shift Out) | 不用切换 |
00001111 | 15 | 0F | SI (Shift In) | 启用切换 |
00010000 | 16 | 10 | DLE (Data Link Escape) | 数据链路转义 |
00010001 | 17 | 11 | DC1/XON | 设备控制1/传输开始 |
00010010 | 18 | 12 | DC2 (Device Control 2) | 设备控制2 |
00010011 | 19 | 13 | DC3/XOFF | 设备控制3/传输中断 |
00010100 | 20 | 14 | DC4 (Device Control 4) | 设备控制4 |
00010101 | 21 | 15 | NAK (Negative Acknowledge) | 无响应/非正常响应/拒绝接收 |
00010110 | 22 | 16 | SYN (Synchronous Idle) | 同步空闲 |
00010111 | 23 | 17 | ETB (End of Transmission Block) | 传输块结束/块传输终止 |
00011000 | 24 | 18 | CAN (Cancel) | 取消 |
00011001 | 25 | 19 | EM (End of Medium) | 已到介质末端/介质存储已满/介质中断 |
00011010 | 26 | 1A | SUB (Substitute) | 替补/替换 |
00011011 | 27 | 1B | ESC (Escape) | 逃离/取消 |
00011100 | 28 | 1C | FS (File Separator) | 文件分割符 |
00011101 | 29 | 1D | GS (Group Separator) | 组分隔符/分组符 |
00011110 | 30 | 1E | RS (Record Separator) | 记录分离符 |
00011111 | 31 | 1F | US (Unit Separator) | 单元分隔符 |
00100000 | 32 | 20 | (Space) | 空格 |
00100001 | 33 | 21 | ! | |
00100010 | 34 | 22 | " | |
00100011 | 35 | 23 | # | |
00100100 | 36 | 24 | $ | |
00100101 | 37 | 25 | % | |
00100110 | 38 | 26 | & | |
00100111 | 39 | 27 | ' | |
00101000 | 40 | 28 | ( | |
00101001 | 41 | 29 | ) | |
00101010 | 42 | 2A | * | |
00101011 | 43 | 2B | + | |
00101100 | 44 | 2C | , | |
00101101 | 45 | 2D | - | |
00101110 | 46 | 2E | . | |
00101111 | 47 | 2F | / | |
00110000 | 48 | 30 | 0 | |
00110001 | 49 | 31 | 1 | |
00110010 | 50 | 32 | 2 | |
00110011 | 51 | 33 | 3 | |
00110100 | 52 | 34 | 4 | |
00110101 | 53 | 35 | 5 | |
00110110 | 54 | 36 | 6 | |
00110111 | 55 | 37 | 7 | |
00111000 | 56 | 38 | 8 | |
00111001 | 57 | 39 | 9 | |
00111010 | 58 | 3A | : | |
00111011 | 59 | 3B | ; | |
00111100 | 60 | 3C | < | |
00111101 | 61 | 3D | = | |
00111110 | 62 | 3E | > | |
00111111 | 63 | 3F | ? | |
01000000 | 64 | 40 | @ | |
01000001 | 65 | 41 | A | |
01000010 | 66 | 42 | B | |
01000011 | 67 | 43 | C | |
01000100 | 68 | 44 | D | |
01000101 | 69 | 45 | E | |
01000110 | 70 | 46 | F | |
01000111 | 71 | 47 | G | |
01001000 | 72 | 48 | H | |
01001001 | 73 | 49 | I | |
01001010 | 74 | 4A | J | |
01001011 | 75 | 4B | K | |
01001100 | 76 | 4C | L | |
01001101 | 77 | 4D | M | |
01001110 | 78 | 4E | N | |
01001111 | 79 | 4F | O | |
01010000 | 80 | 50 | P | |
01010001 | 81 | 51 | Q | |
01010010 | 82 | 52 | R | |
01010011 | 83 | 53 | S | |
01010100 | 84 | 54 | T | |
01010101 | 85 | 55 | U | |
01010110 | 86 | 56 | V | |
01010111 | 87 | 57 | W | |
01011000 | 88 | 58 | X | |
01011001 | 89 | 59 | Y | |
01011010 | 90 | 5A | Z | |
01011011 | 91 | 5B | [ | |
01011100 | 92 | 5C | \ | |
01011101 | 93 | 5D | ] | |
01011110 | 94 | 5E | ^ | |
01011111 | 95 | 5F | _ | |
01100000 | 96 | 60 | ` | |
01100001 | 97 | 61 | a | |
01100010 | 98 | 62 | b | |
01100011 | 99 | 63 | c | |
01100100 | 100 | 64 | d | |
01100101 | 101 | 65 | e | |
01100110 | 102 | 66 | f | |
01100111 | 103 | 67 | g | |
01101000 | 104 | 68 | h | |
01101001 | 105 | 69 | i | |
01101010 | 106 | 6A | j | |
01101011 | 107 | 6B | k | |
01101100 | 108 | 6C | l | |
01101101 | 109 | 6D | m | |
01101110 | 110 | 6E | n | |
01101111 | 111 | 6F | o | |
01110000 | 112 | 70 | p | |
01110001 | 113 | 71 | q | |
01110010 | 114 | 72 | r | |
01110011 | 115 | 73 | s | |
01110100 | 116 | 74 | t | |
01110101 | 117 | 75 | u | |
01110110 | 118 | 76 | v | |
01110111 | 119 | 77 | w | |
01111000 | 120 | 78 | x | |
01111001 | 121 | 79 | y | |
01111010 | 122 | 7A | z | |
01111011 | 123 | 7B | { | |
01111100 | 124 | 7C | | | |
01111101 | 125 | 7D | } | |
01111110 | 126 | 7E | ~ | |
01111111 | 127 | 7F | DEL (Delete) | 删除 |
图为国际标准ASCII码表
他是一个通用标准,被广泛使用,可以让不同公司制造的计算机来互相交换数据,有“互用性”。但是他是为英语设计的
ASCII码表用的是七位,但是一个字节有八位,这就让128到255的字符变得常用,给各个国家自己使用,而在美国,这些位置被用来表示别的符号,比如数学的,物理的等等
但是每个国家的文字有着巨大差异,中国字更是超过了一千个,而有的国家的电脑打开文件之后,则会直接变成乱码(mojibake),为了解决这个问题,每个国家都发明了多字节编码方案,但是都不是互相兼容的,不能实现互用性,因此Unicode出现了,解决了这个问题
最常见的Unnicode是16位的,有超过100万个位置,对于所有语言都够用了
就像用ASCII码表来表示字符一样, 用二进制来编码声音,颜色等等,表示照片/电影/音乐等等
这些归根到底还都是一长串位而已,短信,视频,网页,甚至操作系统,都只不过是一长串0和1
7.编码——可靠性编码(格雷码,奇偶校验码)
格雷码
格雷码是一个数列集合,相邻两数间只有一个位元改变,为无权数码,且格雷码的顺序不是唯一的。
Gray Code是一个数列集合 ,每个数使用二进位来表示 ,假设使用n位元来表示每个数好了 ,任两个数之间只有一个位元值不同,
例如以下为3位元的Gray Code:
000 001 011 010 110 111 101 100
由定义可以知道,Gray Code的顺序并不是唯一的,例如将上面的数列反过来写,也是一组GrayCode:
100 101 111 110 010 011 001 000
由于Gray Code相邻两数之间只改变一个位元,所以可观 察Gray Code从1变0或从0变1时的位置,假设有4位元的Gray Code如下:
0000 0001 0011 0010 0110 0111 0101 1000
1100 1101 1111 1110 1010 1011 1001 1000
重点结论:
(1)观察奇数项的变化时,我们发现无论它是第几个Gray Code,(观察该奇数项的前一项偶数项并与其对比)永远只改变最右边的位元,如果是1就改为0,如果是0就改为1。
(2)观察偶数项的变化时,(观察该偶数项的前一项奇数项并与其对比)我们发现所改变的位元,是由右边算来第一个1的左边位元。
(3)枚举观察发现,随着位元个数的增大,该位元数下的格雷码的数量是2的(位元数)次幂。
以上两个变化规则是固定的,无论位元数为何;所以只要判断位元的位置是奇数还是偶数,就可以决定要改变哪一个位元的值。
传统的二进制系统例如数字3的表示法为011,要切换为邻近的数字4,也就是100时,装置中的三个位元都得要转换,因此于未完全转换的过程时装置会经历短暂的,010,001,101,110,111等其中数种状态,也就是代表着2、1、5、6、7,因此此种数字编码方法于邻近数字转换时有比较大的误差可能范围。格雷码的发明即是用来将误差之可能性缩减至最小,编码的方式定义为每个邻近数字都只相差一个位元,因此也称为最小差异码,可以使装置做数字步进时只更动最少的位元数以提高稳定性。
数字0~7的编码比较如下:
十进制 格雷码 二进制
0 000 000
1 001 001
2 011 010
3 010 011
4 110 100
5 111 101
6 101 110
7 100 111
奇偶校验码
计算机内部二进制数据可能因为一些不可控的因素而出现错误,所以我们必须检验这些错误
假设我们有两种对数据A、B、C、D的编码方式:
1.
信息 A B C D
编码 00 01 10 11
信息 A B C D
编码 100 001 010 111
这其中的编码就是码字:由若干位代码组成的一个字叫码字(码字包含了合法码字和不合法码字,如第二种ABCD的编码方式种101就是不合法的码字)
将两个码字逐位对比,具有不同的位的个数被称为两个码字间的距离,如00和11的距离为2(该位置的数字不同则计一个距离,并不是真实的距离)
一种编码方案中可能有若干个合法的码字,各合法码字间的最小距离被称为“码距”,如第一种d=1,第二种d=2
当d=1时,无校验能力;当d=2时,有校验能力(奇偶校验码);当d>=3时,若设计合理,可能有校验甚至纠错能力(如海明码)。
若有n个有效信息位,可在首部或尾部加上1位的奇偶校验位
奇偶校验码的定义也很简单,整个校验码中1的个数为奇数还是偶数,例
求1001101的奇偶校验码
易知1001101有4个1,假设我们在首部加奇偶校验位
则奇校验码为11001101,偶校验码为01001101
同样最后数据传输校验时,也是以这种奇数或偶数个1进行校验。但值得注意的是,如果发生了2bit位的错误(偶数个位发生变化),奇偶校验码将没用了。
但上述都是我们人类对于奇偶的计数统计,对于计算机只需要对所有信息位进行异或操作就可以实现求偶校验位和进行偶校验
如对于1001101的求偶校验位:
所有位的依次异或得到0,故1001101的偶校验位为0
对01001101进行偶校验,若结果为1说明出错
01001101的异或结果为0,故没错
八、计算机内部二进制算术运算
原码反码补码:
由于计算机的硬件决定,任何存储于计算机中的数据,其本质都是以二进制码存储。
根据冯·诺依曼提出的经典计算机体系结构框架,一台计算机由运算器、控制器、存储器、输入和输出设备组成。其中运算器只有加法运算器,没有减法运算器(据说一开始是有的,后来由于减法运算器硬件开销太大,被废了)。
所以计算机中没办法直接做减法的,它的减法是通过加法实现的。现实世界中所有的减法也可以当成加法的,减去一个数可以看作加上这个数的相反数,但前提是要先有负数的概念,这就是为什么不得不引入一个符号位。符号位在内存中存放的最左边一位,如果该位位0,则说明该数为正;若为1,则说明该数为负。
而且从硬件的角度上看,只有正数加负数才算减法,正数与正数相加,负数与负数相加,其实都可以通过加法器直接相加。
原码、反码、补码的产生过程就是为了解决计算机做减法和引入符号位的问题。下面我们来带着这个问题一一引入原码反码补码他们的概念以及用途:
原码:是最简单的机器数表示方法,用最高位表示符号位,其他位存放该数的二进制的绝对值。
以带符号位的八位二进制数的一部分为例:
一定要注意一件事:八位二进制数指的就是实实在在的八位数字,而并不是四个数字,四个数字那是四位,我们计算n位二进制数能表示的最多值时用的公式是2^n,其原理是每位上的数字可能会变,所以每位上的数字可能有两种情况,所以才会用2^n这个公式
数值 | 二进制原码 | 数值 | 二进制原码 |
1 | 0001 | -1 | 1001 |
2 | 0010 | -2 | 1010 |
3 | 0011 | -3 | 1011 |
4 | 0100 | -4 | 1100 |
5 | 0101 | -5 | 1101 |
6 | 0110 | -6 | 1110 |
但是仔细观察后我们会发现,拿1和-1的原码举例:1的原码是0001,-1的原码是1001,他们相加后是1010,变现成十进制就是-2,而不能得出0
这就引出了反码:
如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数
反码的设计思想就是为了解决一对十进制相反数对应的原码相加再转为十进制,结果不为0的情况
既然一个负数是一个正数的相反数,那干脆把一个正数的二进制按位取反来表示他的负数
正数的原码和反码一致,而负数的反码就是他的原码除符号位外,按位取反,原先是0的变成1,原先是1的变成0.
正数 | 正数的原码(反码相同) | 负数 | 负数的原码 | 负数的反码 |
1 | 0001 | -1 | 1001 | 1110 |
2 | 0010 | -2 | 1010 | 1101 |
3 | 0011 | -3 | 1011 | 1100 |
4 | 0100 | -4 | 1100 | 1011 |
5 | 0101 | -5 | 1101 | 1010 |
6 | 0110 | -6 | 1110 | 1001 |
反码的对应值相加:0001与1110相加:值为1111,转换为十进制为-8,结果显然不对,我们要的是0000,那就加一个数,让其溢出就好了
补码:
正数与0的原码反码补码都一致,负数的补码等于反码加一.
负数的补码等于反码加1,只是其求法,并不是补码的定义。《计算机组成原理》中会用模和同余的概念,严格的解释补码。
计算机的机器数就是这个数对应的带符号位的二进制数字
而真值不是这样的,计算机的真值是指计算机的机器数对应的真实数字(不考虑符号位,比如-1的八位机器数为10000001也即131,真值指的就是机器数的形式值)
原码指的是带符号位的二进制数字,因此,在八位二进制原码数字中,只能够表示[11111111,01111111]这段的数字,所以只能够表示从-127到127的数字,因为第一位是符号位,少表示了两个数字-128和128
正数的反码是他本身,负数的反码是除了符号位之外的所有位上的值进行取反
因此负数的反码同样能从01111111到11111111这段的数字
首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减,但是对于计算机,加减乘数已经是最基础的运算, 要设计的尽量简单.。计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道,,根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。
于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.
为了解决原码做减法的问题, 出现了反码:
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
于是补码的出现,解决了0的符号以及两个0编码的问题:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].
因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.
然后我们来看一下 1 + (-1) 的二进制计算过程: 00000001 + 11111111 = 100000000,得到的是一个 9 位的二进制数,比原来的 8 位多出了 1 位,由于硬件物理上的限制计算机会忽略掉最高位的溢出。因此在计算机看来相加的结果是 00000000,这也就满足了 1 + (-1) = 0。同理,对一个二进制负数求补数,就可以得到相应的正数