定点数与浮点数

定点数与浮点数

一些内容参考自

《计算机组成原理微课版》

《计算机科学导论》

网络内容

大纲

机器表示数
浮点数
定点数
定点整数
定点小数

定点数采用原码和反码表示有两个零,即正零和负零。使用补码和移码表示有一个0。

定点数

  • 定点小数:小数点固定在符号位后面
  • 定点整数:小数点固定在最后一位有效数字后面

C语言中char/short/int/long都是补码表示的定点整数

类型表示范围(补码)
定点小数 − 1 ≤ x ≤ 1 − 2 − n {-1 \le x \le 1-2\mathop{{}}\nolimits^{{-n}}} 1x12n
定点整数 − 2 n ≤ x ≤ 2 n − 1 -2\mathop{{}}\nolimits^{{n}} \le x \le 2\mathop{{}}\nolimits^{{n}}-1 2nx2n1

原因:不算符号位,数值位有n位。

在符号位为正(就是0)且当n位全为1时数最大,为 2 n − 1 2\mathop{{}}\nolimits^{{n}}-1 2n1

在符号位为负时,由于是补码表示,所以模为 2 n + 1 2\mathop{{}}\nolimits^{{n+1}} 2n+1,用a表示模数,那么对于一个负数x,有x = x + a

也就是超过模数范围的应当补全或者舍弃模数。就好比钟表数制是12的模,那么16点相当于4 = 16 - 12

补码的运算相当于:非负数补码即真值,负数则补码等于真值加模数

那么-111111(n个1)就相当于该数再加上 2 n + 1 2\mathop{{}}\nolimits^{{n+1}} 2n+1

这相当于什么?相当于把整个数轴的负数部分移到了正数最大值的右边。跟移码很像,但是是部分的偏移。这其中移过去的也包含原本存在的"负零"那个值,但是就不再表示负0了。

我也不知道弄啥图片描述

//比如说1位符号加4位数值
//从-15到15有32个数(正负0的存在)
-15  ............. -2  -1    -0    0     1    2 ... 14   15
11111 ............... 10001 10000 00000 00001 ........  01111
//-15偏移到15右面需要加上1+2^5
//此时16到31表示负数,由于数是递增的,左侧最小,右侧最大
//如果负数区(16~31)最右侧是-1,那么最左侧的16表示的就是-16

所以不难理解补码表示下的数值位有n位的定点整数范围是 − 2 n ≤ x ≤ 2 n − 1 -2\mathop{{}}\nolimits^{{n}} \le x \le 2\mathop{{}}\nolimits^{{n}}-1 2nx2n1

理解了定点整数就不难理解定点小数。把n位数值位的定点整数范围除以 2 n 2\mathop{{}}\nolimits^{{n}} 2n就能得到它的范围。

01111  //十进制是15
0.1111 //十进制是0.9375
//0.9375=1-2^4

一个二进制整数小数点左移一位就是除二,对于数据位为n位的二进制数,左移n为到数值位之前,符号位之后,就是除以2^n ,动态缩小的范围也需要除以这个。为什么能除?因为范围是依靠最大值和最小值确定的,最大值和最小值按照1/(2^n)的比例变化了,范围也会按照这个比例变化。

浮点数

从定点数过渡到浮点数的理解是这样的:定点数的定长的。因此表示的数据范围是一定的(知道数据位n一定能知道表示的范围),如果小数点是浮动的,那么就能扩大它的表示范围和它的精度

//对于一个小数,定点数的小数点肯定放到个位后面(如下)
0.00000000114514
 ▲

//经过适当的处理,这个小数点能不能放到真正有效数字的前面呢?
0.00000000 114514
          ▲

浮点数顾名思义,点是浮动的。这与它的储存结构无关。

二进制浮点数采用了类似于十进制科学计数法的表示方法。

一个科学计数法例子是 1.1 × 10 − 1 {1.1 \times 10\mathop{{}}\nolimits^{{-1}}} 1.1×101,它需要一个小数,和一个以十为底的幂。

二进制数表示则是:

N = 2 E × M = 2 ± E × ( ± 0. m ) {N=2\mathop{{}}\nolimits^{{E}} \times M=2\mathop{{}}\nolimits^{{ \pm E}} \times \left( \pm 0.m \right) } N=2E×M=2±E×(±0.m)

N是二进制数。尾数M是定点小数,取值范围是 M ∈ [ 1 , 2 ) {M \in \left[ 1,2 \right) } M[1,2),阶码E是定点整数。与科学计数法相比最显著的区别就是科学计数法的阶码是以10位底的,这里则是以2为底的。

在十进制的科学计数法Mantissa x Base^Exponent中,尾数M的取值范围是 M ∈ [ 1 , 10 ) {M \in \left[ 1,10 \right) } M[1,10),也就是说诸如 0.1 × 10 3 0.1 \times 10\mathop{{}}\nolimits^{{3}} 0.1×103这样的是不对的。

那么二进制的浮点数表示法类有没有类似规则呢?有,即规格化处理

规格化处理要求尾数的最高位为1,也就是尾数的绝对值应当大于二进制的0.1或者十进制的0.5,比如说用6位储存的尾数中,001101不是一个合格的尾数,而100010是一个合格的尾数,判断依据是最高位是否为1。

事实上既然最高位是确定的,因此还可以不表示最高位,这样能够多表示一位数据。到时候给数据前面补一个1就行了。基于这点,被隐藏的最高位被称为隐藏位

上面讲的内容不难推出二进制浮点数的储存结构类似于下面这般。

|阶符|----阶数----|数符|----尾数----|

一个明显的问题是,虽然很明显阶符只有正负,也就是只需要一位来储存,但是阶数并不知道是多少位来表示的。

也因此在整个浮点数概念下存在很多标准,这些标准使用大同小异的方法表示浮点数,但通常有精度的差异。

IEEE754

IEEE于1985年发布IEEE754标准,是当今主流采用的浮点数标准。包括32位单精度浮点数和64位双精度浮点数,在C语言中就是熟悉的floatdouble两种类型。

其中32位的浮点数储存结构如下所示、

|--1位--|--8位--|---23位---|
| 数符S | 阶码E |   尾数M   |
|-------|  移码 |  定点小数 |

由于单精度浮点数阶码E按移码储存,其偏移量是127,因此单精度浮点数也被叫做余127码(计算机科学导论P37底部),类似地,该标准所规定的双精度浮点数也被称作余1023码(Excess_1023)。

例如对于E=1000 0011得到真值应当由它减去127,即1000 0011-0111 1111=0000 0100

采用定点小数储存的尾数M,默认小数点在M的最左侧,且小数点左侧还有一个隐藏的1.因此实际有效位数会多一位变成24位。

书中指出浮点数的尾数M可以看做原码储存。它始终是个正数,因为若有符号,该符号会在S中储存。

储存的步骤如下(源自计算机科学导论一书)

  • 在S中储存符号
  • 将数字转换为二进制
  • 规范化
  • 找到E和M的值
  • 连接SEM。

注1:阶码E和尾数M都为0时表示0,并且存在+0-0两个。

注2:十进制小数大多数不能精确转换为二进制小数,转换会因四舍五入产生误差。

注3:在对误差极其敏感的场合建议使用十进制浮点数进行运算。


对于单精度阶码E采用8位储存,即最大为255。对于读取分为两种情况:

  • E=255可以表示无穷大或者NaN(Not a Number)
  • E ∈ [ 1 , 255 ) E \in \left[ 1,255 \right) E[1,255)则有 N = ( − 1 ) S × 2 E − 127 × 1. M N= \left( -1 \left) \mathop{{}}\nolimits^{{S}} \times 2\mathop{{}}\nolimits^{{E-127}} \times 1.M\right. \right. N=(1)S×2E127×1.M
  • E==0&&M!=0时则有 N = ( − 1 ) S × 2 − 126 × 0. M N= \left( -1 \left) \mathop{{}}\nolimits^{{S}} \times 2\mathop{{}}\nolimits^{{-126}} \times 0.M\right. \right. N=(1)S×2126×0.M

其中, E ∈ [ 1 , 255 ) E \in \left[ 1,255 \right) E[1,255)时按规格化数储存,E==0&&M!=0时则按非规格化处理。

非规格化的目的是提高表示精度。原因是如果按照规格化处理,表达式是 N = ( − 1 ) S × 2 − 127 × 1. M N= \left( -1 \left) \mathop{{}}\nolimits^{{S}} \times 2\mathop{{}}\nolimits^{{-127}} \times 1.M\right. \right. N=(1)S×2127×1.M,其中2的幂次是 − 127 -127 127,如果不按照规格化储存则是 − 126 -126 126。这两个区别如下:

对于相同的尾数M=00000000000000000000001

如果是非规格化数:0.00000000000000000000001(小数点后面23位)再把小数点左移126位,结果是 2 − 149 2^{{-149}} 2149

而规格化储存的话最小数是1.00000000000000000000001(小数点后面23位)再把小数点左移127位,显然这个比上面那个大。

显然,使用非规范化数可以表示比规范化数更小的数值(提高精度),当然非规范化数的使用也会带来一些性能开销。

单精度与双精度的相关储存位示图可以在 binaryconvert.com 进行直观验证。

二者的综合比较

不论是定点数还浮点数,能够表示的范围都是不是整个数轴,只能表示数轴上的一部分,就好像那些数轴的刻度一样。并且定点数的刻度是均匀的,浮点数的刻度不是均匀的。越靠近0越密集。

图源来自计算机组成原理微课版(谭志虎主编)

浮点数表示范围

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值