第三章——计算机进行小数运算时出错的原因(计算机如何处理浮点数)

原创
2020/10/11 19:54
阅读数 337
  • 二进制0.1,用十进制表示的话是多少
    0.5。
    解析:二进制数的小数点后第一位的位权是2的负一次方 = 0.5。也就是说,
    二进制数0.1转换成十进制数是1 × 0.5 = 0.5(数值的各数位的数值和位权相乘后再相加的结果)

  • 用小数点后有3位的二进制数,能表示十进制数0.8125
    能,1101。
    解析:十进制数转二进制数的小数部分为“乘2取整”,
    0.8125 × 2 = 1.625,
    0.625 × 1 = 1.25,
    0.25 × 2 = 0.5,
    0.5 × 2 = 1.0

  • 将小数分为符号、尾数、基数、指数4部分进行表现的形式称为什么
    浮点数

  • 二进制数的基数是多少
    2

  • 通过把0作为数值范围的中间值,从而在不适用符号位的情况下来表示负数的表示方法称为什么
    EXCESS系统表现

  • 1010 1100.0101 0011这个二进制数,用十六进制表示的话是多少
    AC.53 解析:整数部分和小数部分一样,二进制数的4位,就相当于十六进制数的1位。 二进制数的3位,就相当于八进制的1位

章节重点

  • 计算机进行小数处理的机制
  • 了解计算机在运算时出错的原因以及如何避免这类错误

章节结构

  • 0.1累加到100次也得不到10的现象(引出计算机如何表示小数的问题)
  • 用二进制数表示小数(将二进制小数转换成十进制)
  • 计算机运算出错的原因(二进制表示小数部分的机制决定的)
  • 有小数部分的数——浮点数(表现形式和内部构造)
  • 浮点数的尾数部分和指数部分的表示方法——正则表达式和EXCESS系统
  • 在实际的程序中进行确认
  • 如何避免计算机计算出错
  • 利用二进制和十六进制的特殊关系,缩短数的位数
  • 数学意义上的进制转换

0.1累加到100次也得不到10的现象(引出计算机如何表示小数的问题)

在计算机中0.1累加到100次是得不到10的,这是由计算机处理小数的机制决定的。

用二进制数表示小数(将二进制小数转换成十进制)

我们知道表示一个数,是由数值位权位数基数构成的。
由我们最熟悉的十进制数开始分析所谓的进制数如何表示一个数的。

比如十进制数13和0.34是什么含义

  • 13 其实表示的是1 × 10的1次方 和 3 × 10的0次方,其中1和2表示的是数值10表示是基数1次方0次方表示的是位权,而决定是几次方的是位数

  • 同时我们知道十进制的0.34表示的是3 × 10的-1次方和4 × 10 的-1次方。

分析上面两个十进制数特点我们可以知道,在表示一个数的时候,是以小数点前面一位为基准点,它的位权是0,因此小数部分的第一位的位权是-1.

因此我们可以推理出如何用二进制小数转换成十进制数
二进制的0000.0011 为十进制的0.1875
1 × pow(2,-3) =0.125;
1 × pow(2,-4) =0.0625;

推广应用,任何进制数转换成十进制的方法

更进一步的总结可以得到以下结论,
规则:进制数位权的取值范围是正无穷到负无穷,从左到右依次递减1,其中小数点前面的那一位就是位权为0的位置。

之前我们就知道的一个规则:任何一个进制数转换成十进制数: 只需将各数位数值和位权相乘,然后再将相乘的结果相加即可实现

根据上述两个规则我们可以将任何进制数转变成十进制数

计算机运算出错的原因(二进制表示小数部分的机制决定的)

计算机运算出错的原因是有一些十进制的小数无法转换成二进制数
比如十进制的0.1就无法用二进制数表示。

我们知道二进制数的小数部分转换成十进制,是2的负多少次幂。

  • 而无论是2的负多少次幂相加得到的和都不会等于0.1。

小数点后四位用二进制数表示时的数值范围为0.0000~0.1111。因此这能表示为0.5、0.25、0.125、0.0625这四个二进制数小数点后面的位权组合而成(相加综合)的小数 (16种情况)。

小数点后4位能够用二进制数表示的数值 二进制数是连续的,十进制数是非连贯的

二进制数 对应的十进制数
0.0000 0
0.0001 0.0625
0.0010 0.125
0.0011 0.1875
0.0100 0.25
0.0101 0.3125
0.0110 0.375
0.0111 0.4375
0.1000 0.5
0.1001 0.5625
0.1010 0.625
0.1011 0.6875
0.1100 0.75
0.1101 0.8125
0.1110 0.875
0.1111 0.9375

从上面表中可知,十进制0的下一位就是0.625。因此这中间的小数就无法用小数点后4位数的二进制数来表示。**就算增加二进制数小数点后面的位数,与其对应的十进制数的位数也会增加。虽然这样可以表示更小的数,组合起来可以更接近0.1这个结果。
** 但是无论增加多少位,2的-○○次幂怎么相加都无法得到0.1这个结果

十进制的0.1转换成二进制数是无限循环小数0.00011001100....(1100),类似于十进制的1/3的循环小数是0.3333333(3)

有小数部分的数——浮点数

二进制数1011.0011 这种表示法只是一种纸面上的表现形式,换句话说,只是能书写出来,真正的计算机内部是无法实现的。
此时在计算机中是用下面的方式来用浮点数表示小数的。
浮点数是指用符号尾数基数指数这四部分来表示的小数。

十进制浮点数转换成计算机内部的二进制浮点数的步骤(五步)

  • 第1步,先将十进制浮点数转化成“纸面的”二进制数(这是纯数学意义的进制转换)

  • 第2步,将“纸面意义的”二进制浮点数转换成IEEE标准的二进制浮点数(即计算机内部的二进制浮点数)

    • 第3步,符号位,正数为1,负数为0

    • 第4步,指数部分,将纯数学意义的二进制浮点数用将小数点前面的值固定为1的正则表达式的形式,此时往右移位的得到的是正数,往左移位的得到的是负数,移动多少位;

      用127加上这个数(带上符号,正数为加,负数则实际是减);
      然后再把这个数转换成二进制即得到指数部分(使用的EXCESS系统)

  • 第5步,尾数部分,将小数点前面的值固定为1的正则表达式,移动,使得小数点前面一位始终是1,然后保留小数点后面部分,缺位补0,使其为23位。

  • 浮点数的表现形式(四部分): 符号 m × n^e (n的e次方)
  • 符号:正负号 + 或者 -
  • m:尾数
  • n : 基数
  • e:指数
  • 浮点数的内部构造(三部分):符号部分、指数部分、尾数部分。(有很多种,此为IEEE标准)
  • 符号部分:使用一个数据位来表示数值的符号。该数据位是1时表示负数,0表示正数或0。
    数值的大小由尾数部分和指数部分来表示,小数就是用“尾数部分×2的指数部分次幂”这样的形式来表示的。
    尾数部分:“将小数点前面的值固定为1的正则表达式”
    指数部分:EXCESS系统表现

IEEE关于浮点数的规定

顺序为:符号部分-指数部分-尾数部分

  • 双精度浮点数(共64位)
    符号部分:1位
    指数部分: 11位
    尾数部分:52位

  • 单精度浮点数(共32位)
    符号部分:1位
    指数部分:8位
    尾数部分: 23位

浮点数的尾数部分和指数部分的表示方法——正则表达式和EXCESS系统

指数部分使用的EXCESS系统

使用这种方法主要是为了表示负数时不使用符号位,即用一个正数来表示负数。
比如说我们规定127为0,那么128就相当于0 + 1 =1,那么126就相当于0-1=-1。

在某些情况下,在指数部分,需要通过“负的多少次幂”的形式表示负数。EXCESS系统表现是指,通过将指数部分表示范围的中间值设为0,是的负数不需要使用符号来表示。

  • 比如当指数部分是8位单精度浮点数时,最大值1111 1111 =255,他的中间值为0111 1111 = 127(小数部分舍弃)表示的是0,则8位可以表示的范围-127~128,即-127次幂到128次幂范围。
  • 同理,指数部分是11位双精度浮点数时,最大值为1111 1111 111 =2047,他的中间值为01 1111 1111 1111 1111=1023(小数部分舍弃)表示的是0

单精度浮点数指数部分的EXCESS系统表现

实际的值(二进制数) 实际的值(十进制数) EXCESS系统表现(十进制数)
1111 11111 255 128(255~127)
1111 1110 254 127(= 254 - 127)
... ... ...
0111 1111 127 0(=127-127)
0111 1110 126 -1(=126-127)
... ... ...
0000 0001 1 -126(=1 -127)
0000 0000 0 -127(=0-127)

尾数部分用正则表达式

按照特定的规则来表示数据的形式即为正则表达式。除小数之外,字符串等也都有各自的正则表达式。

  • 十进制的浮点数应该遵循“小数点前面是0,小数点后面第1位不能是0”这样的规则。

如十进制小数0.75有跟多种表现形式,但是根据上述规则,应表示为 “0.75×10的0次幂” 这种形式

  • 而二进制数的浮点数,使用的是"将小数点前面的值固定为1的正则表达式"
  • 将二进制数表示的小数左移或右移数次后(这里是逻辑移位(即补0)。因为符号位是独立的)。
  • 整数部分的第1位变为1,第2位之后都变为0(这样是为了消除第2位以上的数位)。注意:整数部分的位数是从左到右依次增加1的
  • 而且,第1位的1在实际的数据中不保存。
  • 因此省略该部分后就节省了一个数据位,从而就可以表示更多的数据范围。

单精度浮点数的正则表达式的具体例子
单精度浮点数中,尾数部分是23位,但由于第1位的1被省略了,所以实际上可以表示24位的数值。双精度浮点数的表示方法也是如此,只是位数不同而已。

1011.0011 原始数值
0001.0110011 右移使整数部分的第1位
0001.011 0011 0000 0000 0000 0000 确保小数点以后的长度为23位
011 0011 0000 0000 0000 0000

十进制0.75作为单精度浮点数在计算机中存储的形式

  • 首先,计算机内部都是以二进制形式存储的。

  • 第二步,将十进制0.75用"纸面的二进制形式表示"(有小数点的二进制形式),根据十进制小数部分转换成二进制小数部分,“乘2取整”的规则,得到0.1100

  • 第三步,纸面的二进制数使用科学计数法形式,即小数就是用“尾数部分×2的指数部分次幂”这样的形式来表示,1.1 × 2的 -1 次幂(科学计数法)

  • 第四步,根据浮点数指数部分使用的是EXCEED系统表现,-1也就是127 +( -1 )=126(十进制形式),转换成二进制则为0111 1110。因此指数部分为0111 1110

  • 第五步,尾数部分:用的是正则表达式,将小数点前面的值固定为1的正则表达式

  • 0.1100为了得到整数第1位为1(从小数点开始往左边的顺序),需要逻辑左移1次,变为1.100,
  • 补0,确保小数点以后的长度为23位,得到1.100 0000 0000 0000 0000 0000
  • 仅保留小数点后面的部分,完成正则表达式,得到100 0000 0000 0000 0000

综上所述,在计算机中0.75是以符号位-指数部分-尾数部分

1-0111 1110-100 0000 0000 0000 0000

如何避免计算机计算出错

  • 回避策略,即无视这些错误。因为有些计算不需要那么精确,允许误差,所以可以忽视这种问题。
  • 另一种方法则是,将小数转换成整数计算(前提是保证不超过可处理的数值范围),然后再把计算结果用小数表示出来即可。

利用二进制和十六进制的特殊关系,缩短数的位数

在以位位单位表示数据时,使用二进制数比较方便,但是也容易出现位数太多的问题。
二进制数的4位,正好相当于十六进制数的1位。因此在实际编程中常常用十六进制数代替二进制数。如在C语言中,只需在数值的开头加上0x(0和x)就可以表示十六进制数了。

用十六进制数来表示二进制数小数

小数点后的二进制数的4位也相当于十六进制数的1位。不够4位时用0填补二进制数的低位即可

如1011.011(二进制)转换成十六进制
低位补0,得到1011.0110,1011为B,0110为6 因此为B.6

十进制数转二进制数 正数部分为“除2取余”,小数部分为“乘2取整”,
102.625

  • 正数部分: 1100110 除2取余,直到商为0为止(即除数大于被除数时)
除2 余数
101/2 51 0
51/2 25 1
25/2 12 1
12/2 6 0
6/2 3 0
3/2 1 1
1/2 0 1
  • 小数部分:101
    乘2取整,直到积的小数部分为0为止
乘2 整数
0.625 * 2 1.25 1
0.25 * 2 0.5 0
0.5 * 2 1.0 1

数学意义上的进制转换

十进制数转n进制数

正数部分为“除n取余”,小数部分为“乘n取整”

非十进制数之间的转换

  • 二进制数转换成八进制数 二进制数的3位相当于八进制数的1位
  • 二进制数转换成十六进制数 二进制数的4位相当于十六进制数的1位
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部