定点数与浮点数(小数)

计算机中机器数的类型:定点数(整数)与浮点数(小数)

本文内容参考自王达老师的《深入理解计算机网络》一书<中国水利水电出版社>

一、计算机中一共有两种机器数类型:

机器数就是计算机中参与运算的有符号二进制数,其实,它与我们平时使用的十进制一样,有整数也有小数,但是关键在于,如果二进制与我们平时书写十进制小数一样,带上一个".",那么二进制受困于存储器中字长的限制,无法灵活地表示小数的小数点("."),所以,二进制的小数在存储器中的表示形式与我们平时书写的十进制数时不一样,需要对小数点进行特别的处理,这也就有了我们接下来将要重点介绍的"定点数"与"浮点数"之分。
–引用自王达老师《深入理解计算机网络》一书

你可以先思考一下,为什么带上".",二进制会受困于存储器中字长的限制,导致无法灵活地表示浮点数(小数)呢?
解释:这是一个很古老的故事了,因为,机器只能认识0,1两种表示,那么,你如果想在机器中表示".",要么用0,要么用1,比如:
十进制的3.1,假设我们用0来表示这个".",那么3.1转换成二进制就是011 0 00011,这里有两个非常巨大的漏洞,首先,011000011也是十进制数195的二进制表示,那么计算机无法辨别到底是195还是3.1,其次,就算能用0来表示".",那么011之后有4个0,到底第几个0才是表示那个小数点的0?所以,用0表示小数点不行,那么用1表示呢?用1也不行,和用0表示缺点是一样的。
那么我们是否能规定字长中的第几位是表示小数点?可以,比如我们规定字长为64位的存储器中的第32位为小数点,那么,这就损失了灵活性,因为,你既然规定了第32位为小数点,这是固定不变的,那么第一位肯定是符号位了,所以表示整数部分的位数只剩下了第2位到第31位,表示小数部分的位数只剩下了第33位到第64位(小数点左边是整数部分,右边是小数部分),既然规定了位数,那么这个定长所能表示的数值范围就极大受限了,从以上分析来看,二进制无法像十进制那样通过"."直观表示一个浮点数,那么怎么样来表示一个浮点数合适呢?文章"浮点数"章节会详细说明。

整数类型的机器数很好表示,只是在最高位多了一个符号位,小数点总是在最右端,完全可以直接忽略,就像我们书写十进制整数时一样,但如果是小数,小数点是不能不考虑的,上文提到了,在计算机中,".“不像我们平常书写十进制那样好处理,因为为了保持灵活性,不可能在计算机的存储器里面固定拿一位出来表示”.",所以,计算机的存储器是没有专门的位来表示小数点的。
为了能使计算机自动识别机器数的小数点位置,正确识别对应机器数的大小,依据机器数中小数点的位置是否固定把所有的机器数分为两类:定点数和浮点数(之所以叫浮点数,其实是很形象的,因为小数点在不同的浮点数之间总是"浮来浮去",不是固定的)。
–引用自王达老师《深入理解计算机网络》一书

  • 1、定点数
    定点数又细分为两类:定点整数,定点小数:
    • ⑴、定点整数
      定点整数是小数点固定在有效数值部分最低位之后的定点数,等于就是纯整数了,如,一个定点整数是n位二进制,那么它的最高位是符号为,所以它能表达的数值范围为:-(2n-1-1)<=X<=2n-1-1。例如一个8位的定点整数,除了最高位表示符号位外,能具体用于表示数值的剩下7位,所以它的最大值是0 1111111,即127,等于27-1,所能表示的最小值为1 1111111,即-127,等于-(27-1)。
    • ⑵、定点小数
      定点小数是小数点位置固定在符号位之后,有效数最高位之前的定点数,是纯小数,如一个定点小数是n位,它的最高位同样是符号位,则它所能表示的数值范围为:-(1-2-(n-1))<=X<=1-2-(n-1)。例如一个8位的定点小数,除了符号位外,用于表示真值的共7位,由此可以得出它所能表示的最大值为0.1111111,即0.5+0.25+0.125+0.0625+0.03125+0.015625+0.0078125=0.9921875(从这里你也能看出来,为什么机器数的表示是有限的。实际上,你看到这里,你马上就能知道,按照这种方式,你无法用机器数表示出0.9921876!因为每一步的叠加都是通过1/2n-1实现的)。等于1-2-7,所能表示的最小值为1.1111111,即-0.9921875,等于-(1-2-7)。

      经验之谈
      一个n位连续为1的正二进制整数的值是2n-1(n-1是因为最高位是符号位)。
      一个n位连续为1的负二进制整数的值是-2n-1(n-1是因为最高位是符号位)
      一个n位连续为1的整二进制小数的值是1-2-n,不再需要将每位转换成十进制再相加,直接1-2-n就行,同理,一个n位连续为1的负二进制小数 的值是-(1-2-n)。

  • 2、浮点数
    我在上文中已经分析了,计算机中二进制如果要表示即有整数又有小数的定点数(这里称为定点数的意思就是在存储器中固定一位,让它表示".")不可能像书写十进制小数那样方便(意思就是表示中不可能包括"."),实际上的解决办法还是需要通过0和1来表示,但是表示方法需要换一下,说直白一些,我们实际使用的表示即有整数又有小数的二进制表示法不包括".",计算机可以通过实际的表示确定小数点的具体位置,其实就是"浮点数法"–这种表示法很灵活,可以表示任何小数,同时也充分利用的计算机的字长,表示的范围也比定点法扩大好多倍,实际应用起来没有一点问题。
    这里通过实际的举例来说明"浮点",比如12.23中".“是在第3位,1.223中”.“是在第2位,1099.25中”.“是在第5位,看上去,不同的数中这个”.“是不是位置不同,浮来浮去的?所以我们很形象地把实际中用来表示即有整数部分又有小数部分的定点数的表示法称为"浮点”。于是乎,即有整数部分又有小数部分的数直接就称为"浮点数"了。
    那么,计算机中是如何灵活地来表示一个浮点数的呢?
    我们知道,在十进制数中,比如123.45用科学计数法可以表达为1.2345 * 22,其中1,2345为尾数,10为进制基数,2为指数,尾数和指数均为十进制表示,如果是负数,在前面加一个"-“就行。
    如果需要将以上内容整理成一个通式表达的话,尾数用M表示,指数用E表示,那么十进制数N的表达通式是:
    N = M * 10E
    按照以上的思路可以得出二进制的表达通式为:
    N = M * 2E(只需要换进制基数就行,将10换成2)。
    但是二进制的表达通式中,尾数M必须是二进制原码格式,指数E也必须是二进制原码格式,E在十进制中称"指数”,但是在二进制通式中称为"阶码"(IEEE 754中是用移码表示)。
    最后一点需要强调的是,浮点数在计算机存储器中存储的格式可以是原码格式,也可以是补码格式,但通常都是补码格式,因为补码格式方便正负数的运算。
    我们再来仔细观察一下这个表达通式:
    :N = M * 2E
    之前直接在存储器中像存储十进制小数一样存储二进制浮点数的方式已经被证明不灵活以及非常受限。那么还有什么办法?
    通过再次对以上通式的观察,我们可以发现,一个浮点数只要知道了它的符号位,指数和尾数,就可以根据以上的通式反推出它的实际值,所以最终的解决办法就是在存储器中分别存数浮点数的符号位,指数位和尾数位,不同的标准对符号位,指数位和尾数为规定的存储位数不同,我们来讨论IEEE 754标准。
    通过表格图示符号位(S),指数(E),尾数(M)的存储顺序:
    符号位 S 指数位 E 尾数位 M
    指数位E的形式实际上就是一个定点整数(纯整数),可以通过它推算出浮点数的小数点位置,所以它也间接决定了浮点数的表示范围,M的形式实际上就是一个定点小数(纯小数),它表示了浮点数的有效值,决定了浮点数的精度(精度说白了就是小数点保留几位)。指数E为正时,表示转换后尾数部分的小数点比原数的小数点位置左移了E位(用十进制举例,更直观,比如123.4变成1.234 * 102,那么1.234的小数点相比123.4左移了2位,二进制也是一个意思,只是进制基数为2),指数E为负时,表示转换后尾数部分的小数点与原数的小数点位置右移了E位。
    如一个浮点数为-0.10101 * 211,则它在16位字长的存储器(假设规定E用4位表示,M用11位表示,S符号位占1位)中的存储格式如下表格:
    符号位 S 指数位 E 尾数位 M
    1 0011 10101000000
    通过以上的分析,我们发现了,实际上所有的浮点数都可以通过移动小数点来变成一个纯小数和一个指数的乘积,同时,为了规范起见,规定机器数的浮点数表达形式中尾数的最高有效位(即小数点右边第一位)不能为0,必须为1,也就是说,不要出现0.00101001 * 2101101这种情况!
    把所有不满足小数点右边第一位必须为1的浮点数变成满足要求格式的过程称为浮点数的规格化处理(实际上就是通过小数点的以为和修改指数来实现)。
    在IEEE 754标准中,把浮点数分成了单精度和双精度两种,同时规定了单精度浮点数长度为32位(4字节),双精度浮点数为64位(8字节)。
    IEEE 754标准中,E和M都是用补码表示,而不是原码,因为补码方便计算。
    这里又有一个问题需要说明,我们都知道,指数E是可以为负的,这样可能导致一个浮点数中出现两个符号位(浮点数自身和浮点数指数的),这样的结果会导致在比较两个浮点数大小时比较麻烦,那么这种问题如何解决呢?
    实际中的解决办法是,可以在指数的基础上加上一个固定的正数(这个正数是无符号的正数,就是说,它所有的二进制位都是它的真值,它没有符号位!),保证指数一定是正的(加的这个正数是固定的)!这种操作在IEEE 754中称为偏移,得到的结果称为"移码"。所以,用移码表示能确保指数部分均为无符号的正数,正数的原码和补码完全一致,不用转换。
    下表提供单精度浮点数和双精度浮点数各部分在存储器中的结构
    浮点数类型 符号所在位(S) 指数所在位(E) 尾数所在位(M) 偏移值(固定的正数)
    单精度浮点数 31(1) 30-23(8) 22-0(23) 127(对应二进制位:01111111)
    双精度浮点数 63(1) 62-52(11) 51-0(52) 1023(对应二进制位:0111111111)
    以上表中的指数E是以"移码"格式表示的,所以IEEE 754 中用于浮点数中小数点位置的移码 = 原指数 + 偏移值。如果用e来表示原来的指数,则有如下关系式:
    e = E + 偏移值
    总结:在计算浮点数时可以用以下公式统一表示:X = S(1.M) * 2E-偏移值,其中X为浮点数原码,S为符号位,M为尾数,E为移码表示,"E-偏移值"就等于原指数。
    PS:可能有的人会异或,为什么是1.M。因为这是格式化,所有的浮点数都可以通过移动指数来格式化,比如二进制的0.1 = 1.0 * 2-1,0.00101 = 1.01 * 2-3。统一了格式便于理解和计算!
    在此,再次感谢王达老师的《深入理解计算机网络》一书对本文的启发!

PS:时间有限,有关计算机基础的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正!

猜你喜欢

转载自blog.csdn.net/ruidianbaihuo/article/details/87884720