4.1 数制
用户在计算机指令代码和数据的书写中经常会使用到数制,数制也称计数制,是用一组固定的符号和统一的规则来表示数值的方法。任何一个数制都包含两个基本要素,基数和位权。虽然计算机能极快地进行运算,但其内部并不像人类在实际生活中使用的十进制,而是使用只包含0和1两个数值的二进制。学习编程,就必须了解二进制、八进制和十六进制。
4.1.1 二进制
二进制是计算机系统中采用的进位计数制。在二进制中,数用0和1两个符号来描述。计数规则是逢二进一,借一当二。当前的计算机系统基本上使用的是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制是一个非常微小的开关,用1来表示“开”,0来表示“关”。
1. 二进制的优点
数字装置简单可靠,所用元件少;只有两个数码0和1,因此它的每一位数都可用任何具有两个不同稳定状态的元件来表示;基本运算规则简单,运算操作方便。
2. 二进制的缺点
用二进制表示一个数时,位数多。因此实际使用中多采用送入数字系统前用十进制,送入机器后再转换成二进制数,让数字系统进行运算,运算结束后再将二进制转换为十进制供用户阅读。
3. 认识二进制
在数据世界里面,十进制是最常用的。那如何用一个十进制数来表示二进制呢?首先计算一个二进制数1111转变成十进制数的过程。
1*20+1*21+1*22+1*23=1*1+1*2+1*4+1*8=15,如图4-1所示。
图4-1 二进制转十进制
由于1111才4位,所以可直接记住它每一位的权值,并且是从高位往低位记8、4、2、1。即,最高位的权值为23=8,然后依次是22=4,21=2,20=1。所以记住8、4、2、1,对于任意一个4位的二进制数,都可以很快算出它对应的十进制值,如图4-2所示。
图4-2 权值相加
二进制和十进制的互相转换是比较重要的。不过这二者的转换却不用计算,每个C++程序员都能做到看见二进制数,直接就能转换为十进制数,反之亦然。
二进制转十进制:按权展开求和。
例:(1011.01)2 =(1×23+0×22+1×21+1×20+0×2(-1)+1×2(-2))10
=(8+0+2+1+0+0.25)10
=(11.25)10
注意:(1011.01)2,这个下标表示1011.01是二进制数。同理,11.25是十进制。
规律:个位上的数字的次数是0,十位上的数字的次数是1,……,0依次递增,而十分位的数字的次数是-1,百分位上数字的次数是-2,……,依次递减。
4.1.2 八进制
八进制是一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进一。一些编程语言中常常以数字0开头表明该数字是八进制。八进制的数和二进制的数可以按位对应(八进制一位对应二进制三位),因此八进制(基数为8)表示法常应用在计算机语言中,我们经常看到人们使用八进制表示法。但由于十六进制一位可以对应4位二进制数字,用十六进制来表示二进制较为方便。因此,八进制的应用性不如十六进制。
八进制与二进制之间的相互转换见表4-1。
表4-1 八进制与二进制转换
八进制转换为二进制,直接替换就可以实现。例如17.36转换成二进制,按照顺序,每1位八进制数改写成等值的3位二进制数,次序不变。
(17.36)8=(001 111 .011 110)2=(1111.01111)2
而将一个二进制数换算为八进制,只需将二进制串划分成每三个位一组(如果需要的话,在前面补零),然后查表4-1,将三位一组的位串替换为相应的八进制数字即可。
4.1.3 十六进制
十六进制是计算机中数据的一种表示方法。同日常生活中的十进制表示法不一样。它由0—9,A—F组成,字母不区分大小写。N进制的数可以用0(N-1)的数表示,超过9的用字母A—F,计数规则是逢十六进一。
编程中,开发者常用的还是十进制,毕竟C/C++是高级语言。不过,由于数据在计算机中的表示,最终以二进制的形式存在,所以有时候使用二进制,可以更直观地解决问题。但二进制数太长了,比如int类型占用4字节,32位。面对这么长的数进行思考或操作,没有人会喜欢。因此,C++没有提供在代码中直接写二进制数的方法。用十六进制或八进制可以解决这个问题。因为,进制越大,数的表达长度也就越短。
不过,为什么偏偏是十六进制或八进制,而不是其他的,诸如九进制或二十进制呢?2、8、16,分别是2的1次方、3次方、4次方。这一点使得三种进制之间可以非常直接地互相转换。八进制或十六进制缩短了二进制数,但保持了二进制数的表达特点。在下面的关于十六进制与二进制的转换表中,可以发现这一点。
十六进制与二进制之间的相互转换见表4-2。
表4-2 十六进制与二进制转换
十六进制转换成二进制相当直接,规则也相仿八进制转换为二进制,按照顺序,每1位十六进制数改写成等值的4位二进制数,次序不变。
例:(FCAD)16=(1111 1100 1010 1101)2
而将一个二进制数换算为十六进制,只需将二进制串划分成每四个位一组(如果需要的话,在前面补零),然后查表4-2,将四位一组的位串替换为相应的十六进制数字即可。
十六进制和二进制、八进制一样,都以2的幂来进位的。
4.1.4 十进制
十进制数用0,1,2,3,4,5,6,7,8,9这十个符号来描述。计数规则是逢十进一。十进制计数法是相对二进制计数法而言的,是日常使用最多的计数方法,它的定义是:“每相邻的两个计数单位之间的进率都为十”的计数法则,就叫作“十进制计数法”。
十进制基于位进制和十进位两条原则,即所有的数字都用10个基本的符号表示,同时同一个符号在不同位置上所表示的数值不同,符号的位置非常重要。基本符号是0到9十个数字。要表示这十个数的10倍,就将这些数字左移一位,用0补上空位,即10,20,30,…,90;要表示这十个数的10倍,就继续左移数字的位置,即100,200,300,…。要表示一个数的1/10,就右移这个数的位置,需要时就0补上空位:1/10位0.1,1/100为0.01,1/1000为0.001。
十进制与二进制之间的相互转换见表4-3。
表4-3 十进制与二进制转换
1. 二进制数转换成十进制数
由二进制数转换成十进制数的基本做法是,把二进制数首先写成加权系数展开式,然后按十进制加法规则求和。这种做法称为“按权相加”法。
2. 十进制数转换为二进制数
十进制数转换为二进制数时,由于整数和小数的转换方法不同,所以先将十进制数的整数部分和小数部分分别转换后,再加以合并。
(1)十进制整数转换为二进制整数。十进制整数转换为二进制整数采用“除2取余,逆序排列”法。具体做法是:用2去除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为零时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
例:(89)10=(1011001)2
89/2=44……1
44/2=22……0
22/2=11……0
11/2=5……1
5/2=2……1
2/2=1……0
1
(2)十进制小数转换成二进制小数采用“乘2取整,顺序排列”法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。
例:(0.625)10=(0.101)2
0.625*2=1.25……1
0.25*2=0.50……0
0.50*2=1.00……1
二进制与十进制的区别在于数码的个数和进位规律,二进制的计数规律为逢二进一,是以2为基数的计数体制。10这个数在二进制和十进制中所表示的意义完全不同,在十进制中就是我们通常所说的十,在二进制中,其中的一个意义可能是表示一个大小等价于十进制数2的数值。