[音乐] 好,到目前为止呢,我们讲
的是规格化数,都是讲的规格化数,
就是小数点前面一定有一个1的,而我们讲规格化数,它的指数部分
是负126到正127,
对应的编码是000001
到111110,也就是1到254,
然后它的尾数小数点后面的这个部分,尾数小数
尾数的小数点后面的部分是任意一个0/1序列,这就是一个规格化的形式,
然后我们刚才讲过全0指数和全1,就是全0的这个阶码,
和全1阶码是用来表示特殊数的, 所以我们还有一些情况,比如说全0阶码,
尾数为0的情况下我们到底表示的是什么数?
全0阶码,然后尾数 非0的时候我们表示什么数?全1阶码
又表示什么数?这是我们后面要讲的, 这个单精度的格式是这样子的,
那么,0的表示是怎么样子的呢?在HB754当中,这个标准当中, 我们用全0指数和全0尾数
来表示0,那么这样的话,符号位是0的时候,就表示正0,
符号位是1的时候就表示负0,这个32位表示 正0,这个32位表示负0,这是0的表示,
那么,我们还可以表示正负无穷大,
比如说某一个有限的浮点数除上0,
就是浮点数除0并不会发生异常,
我们前面讲过整数,一个整数除以0,整除0
得到的是一个整数,是无法表示的, 所以是异常的,但是浮点数除0,它是等于正负无穷大,
它不是溢出异常,为什么要有这样的正负无穷大来表示呢?
是因为我们可以对浮点数在某些情况下进行比较,
比如说我们拿一个浮点数除以0,可以和另外一个浮点数比 那显然是大于,当然x、
y都是正数的情况下, 这是正无穷大,正无穷大和负无穷大
仅在符号位不一样,符号位等于0的时候是正无穷大,符号位等于1的时候是负无穷大,
那么,我们用全1阶码 也就是阶码的十进制对应的是255,
也就是全1的时候,然后 用尾数的小数点后面是全0,
用这样的组合来表示无穷大,表示无穷大,那么在机器里面
很多运算的结果都是正无穷大或者负无穷大,比如说一个有限数除以0,
那它可以能等于正无穷大,或者负无穷大,因为有限数加上无穷大,
它还是无穷大,无穷大加无穷大还是无穷大等等,那么,
有了无穷大的这个表示,一个机器数的表示,我们就可以在程序当中
去计算这些表达式,这些表达式的结果并不会发生异常,
而是确定了一个数,这个确定的数就用上面的这样的0/1序列来表示的。
另外还有的情况下,比如说我们的负数开根号,或者0除0,前面
是一个有限数除以0,那当是0.0除上0.0呢,
它是一个不定的数,我们称为非数,NaN,非数,
那么非数的表示在机器里面,在HB754当中它是用全1的阶码,
和非0的尾数部分来表示的,
这个可以帮助调试程序,假定我们有一个变量是个负数,结果我们对它进行开根号了。
然后我们可以去打印一下它的结果,一看 如果这个结果是这样的一个组合,那我们就可以
判定这个开根号的,求平方根的 这个函数当中的这个参数可能是个负数等等。
如果出现这种结果,我们就可以去调试,去判断这个原因,
而不会让这个程序出现异常,使得我们程序执行不下去,得不到
这个结果,我们也无法去查找原因,所以NaN在机器里面也是非常有用的。
很多情况下的结果都是非数, 好,到目前为止我们讲了很多组合了。
比如说全0阶码,全0尾数的时候,我们表示正负0,
在这个非全0或者非全1的情况 下,我们表示的是规格化数,全1的这个阶码
和全0尾数的时候,我们表示正负无穷大,
然后全1的阶码,非0尾数的时候,我们表示非数,
在这个里面还有一种组合,就是全0指数,
全0的阶码和非0的尾数的时候,我们前面还没讲,
那么,这种组合我们后面讲到它是用来表示非规格化数,
这下面的这个是规格化数,小数点前面一定是一个1,
那么,非规格化数肯定大家能够猜到,就是小数点前面是0,
小数点后面也还有若干个0,它是一个非规格化数,
我们来看看规格化数在数轴上, 最小的规格化数,
最小的这个规格化数对于正数来说是2的负126,
这是最小的规格化数,也就是 它的这个值应该是
这是最小的,从往右边的都是规格化数,
这个负的2的负126,最小的2的负126, 就是等于1.0000乘上2的负126,
因为这个最前面的这个1是不表示的, 所以它的这个
significant 那部分就是小数点后面的尾数部分是全0,
然后它的指数应该是000001, 000001,所以2的负126,它的这一个
机器数,我们很快就能写出来,它的机器数应该是
符号,因为它是正数,所以符号等于0,然后它的阶等于负126,
它的指数等于负126,对应的阶码 就是127
加负126,那就是000001
然后它的尾数部分1,第一个 1,前面这个1不用写,然后只写小数点后面的,
所以这个这一个机器数, 就是2的负126次方的机器数,
那么,在
这个地方是2的负125,这个地方是2的负124,是这样子的。
所以我们可以看到这个区间,这个区间的长度是2的负125减去2的负126,所以
这个长度是2的负126,从这一个位置 到这个位置,它的长度是2的负125,
显然2的负125是2的负126的2倍, 所以这边的这个数之间的间距,
是这边这个数之间的间距的2倍。
因为从2的负126到2的负125
这边的这个数的个数应该是多少? 应该是2的23次方个数,
因为这边的这个小数点后面的 significant
尾数部分 表示23位,可以表示23位,所以这边的这个数是00000,23个0,
然后紧接着后面的这个数的尾数,小数点后面是00000001,
然后再后面一个数是0000010,最后一个是1111111111,23个1, 所以这边一共可以表示2的23次方个数,
然后从这个数到这个数之间, 也是可以表示2的23次方个数,
而这个区间是它的2倍,因此,相邻的两个可表示数之间的距离
比这边的距离要大一倍,也是
它的2倍,所以我们可以看出浮点数在数轴上面, 它是越来越稀疏,往无穷大方向上面
那个间隔越来越大可表示数之间的间隔越来越大 那么越离这个原点近的,它的精度
越好,就是数越小的话它的精度越好,表示数之间的距离越小 这个是规格化数。
那么实际上在这个 0和最小的规格化数之间有一大段的这个
GAP,就是间隙,这个间隙我们可以把它利用出来 来表示非规格化数。
这个0实际上尾数全0
阶码可以是这个,那么这个就表示0,然后最大的就是比那个2的负126次方
更小的,那么就是 接近于它的这个非规格化数,最大的应该是
0.1111……,这是最大的尾数,01111……是最大 的尾数。
然后在这个里面的所有的数,它的 指数也就是阶都是负126,都是负126
那么这个里面就是我们称为非规格化数。
所以非规格化数 它的指数或者叫阶,总是负126。
而它的尾数部分 小数点前面一定是0,小数点后面可能是
0000……1,可能是0000……10,可能是11111……全1
也有2的23次方个数在这儿 这是非规格化数。
在机器里面,我们可以表示 用这个数来表示,这种情况来表示非规格化数,也就是
前面我们讲到的这个,前面讲到的
全0阶码的时候,如果 尾数部分是一个非0数的话,那它就是个
非规格化数,所以最后我们可以用这个公式来求 它的真值。
下面我们来看一个例子 一起看一个精度的例子。
刚才我们已经看到了,在数轴上面浮点数它是一些离散的点
也就是说,并不是任何一个数字都可以用IEEE的这个浮点数来表示的,有些数字
它是无法表示的,那么它只能够进行舍入 舍入到一个可表示数。
比如说这边有一个程序 C++的程序,在屏幕上面显示一串字符串
然后呢让你输入一个float型的单精度的float型的一个
值,这个值赋给heads以后,再把它打印出来,在屏幕上 显示出来。
那么这里面有一些例子,比如说我们可以 输入61.419997
然后结果它,从键盘输入的是这个值,屏幕上打印出来
的是这个值,很显然61.419997是一个
不可表示的数,它不能表示,所以它就近似地用这个数表示
然后这个数可表示数,然后61.419999也是 不可表示数,也是要进行舍入的
还是舍入成它,然后61.42 也是不可表示数,舍入以后还是
显示成61.419998 然后在键盘上输入61.4200001
这时候它显示的就不是61.419998,它显示的就是61.42 0002。
那么从这些例子当中我们可以看出 这个数61.419998和61.42
0002是两个可表示数,而这边给出来的这些 除了这个数以外,其他的都不是可表示数。
因此可以看出两者 之间它差别,差了0.000004
相差了0.000004,所以当输入的数据是一个不可表示数的时候
在机器内部它做了舍入到一个最近的一个可表示数显示出来
也就是说在机器里面用32位是无法表示这些数的,无法精确表示这个数
所以只能低位把它丢掉,丢掉了以后你再显示出来的时候,它就不是原来 送进去的那个值了。
这是一个浮点数精度的一个例子 [音乐]
[音乐]