《程序是怎样跑起来的》读书笔记(第三章)——计算机进行小数运算时出错的原因

一、课前热身

1.  二进制数 0.1,用十进制数表示的话是多少?
答:0.5
2.  用小数点后有 3 位的二进制数,能表示十进制数 0.625 吗?
答:可以
3. 将小数分为符号、尾数、基数、指数 4 部分进行表现的形式称为什么?
答:浮点数
4.  二进制数的基数是多少?
答:2
5.  通过把 0 作为数值范围的中间值,从而在不使用符号位的情况下来表示负数的表示方法称为什么?
答:EXCESS系统表现
6.  10101100.01010011 这个二进制数,用十六进制数表示的话是多少?
答:AC.53

二、将 0.1 累加 100 次也得不到 10

  • 这个问题大家可能会觉得不可思议,毕竟计算机在处理很大的数据时一般情况都不会出错,但是怎么会在这么小的计算上出错。这个问题就得从计算机是如何处理小数的机制上去解释了。
  • 首先,我们先来看一下一段程序
    在这里插入图片描述
    这段程序相信大家都看得懂,但是真正运行得到的结果和你预想的一样吗?0.1累加100次,相信大家都知道等于10.0。但是计算机运行的结果却是如下图
    在这里插入图片描述
    看到这个结果,很多人就不理解这最后这个2是怎么来的?我们先接着往下看。

二、用二进制数表示小数

  • 上一章我们已经说过,计算机在计算时,是将其他进制的数值转化为二进制进行计算的,我们先看一下,二进制到十进制的转换过程;
    在这里插入图片描述
  • 二进制数小数点前面部分的位权,第 1 位是 2 的 0 次幂、第 2 位是 2 的 1 次幂……以此类推。小数点后面部分的位权,第 1 位是 2的-1 次幂、第 2 位是 2 的-2 次幂,以此类推。0 次幂前面的位的位权按照 1 次幂、2 次幂……的方式递增,0 次幂以后的位的位权按照-1次幂、-2 次幂……的方式递减。这一规律并不仅限于二进制数,在十进制数和十六进制数中也同样适用。

三、计算机运算出错的原因

  • 在了解了将二进制数表示的小数转换成十进制数的方法后,计算机运算出错的原因也就容易理解了。这里我先把答案告诉大家,计算机之所以会出现运算错误,是因为“有一些十进制数的小数无法转换成二进制数”。比如:0.1就无法用二进制的数值进行表示,因为二进制的0.1和十进制的1/3(0.3333333……)一样,是一个无限循环的形式,十进制数0.1 转换成二进制后,会变成 0.00011001100…(1100 循环)。所以计算机无法准确地表示出一些小数的值。下面这段文字解释了为什么某些小数无法被表示出来。
  • 小 数 点 后 4 位 用 二 进 制 数 表 示 时 的 数 值 范 围 为0.0000~0.1111。因此,这里只能表示 0.5、0.25、0.125、0.0625 这四个二进制数小数点后面的位权组合而成(相加总和)的小数。将这些数值组合后能够表示的数值。
    在这里插入图片描述

四、 什么是浮点数

  • 很多编程语言中都提供了两种表示小数的数据类型,分别是双精度浮点数和单精度浮点数。双精度浮点数类型用 64 位、单精度浮点数类型用 32 位来表示全体小数。
  • 浮点数:是指用符号、尾数、基数和指数这四部分来表示的小数。
    在这里插入图片描述
  • 。因为计算机内部使用的是二进制数,所以基数自然就是 2。因此,实际的数据中往往不考虑基数,只用符号、尾数、指数这三部分即可表示浮点数。也就是说,64 位(双精度浮点数)和 32 位(单精度浮点数)的数据,会被分为三部分来使用。
    在这里插入图片描述
  • 符号部分是指使用一个数据位来表示数值的符号。该数据位是 1时表示负,为 0 时则表示“正或者 0”。尾数部分用的是“将小数点前面的值固定为 1 的正则表达式”,指数部分用的则是“EXCESS 系统表现”

五、正则表达式和 EXCESS 系统

5.1 正则表达式

  • 前面已经讲解过,浮点数的尾数部分使用正则表达式,这样做的目的就是可以将表现形式多样的浮点数统一为一种表现形式。因为浮点数的表达形式种类过多,所以必须的将其进行统一标准处理,从而方便运算。
    在这里插入图片描述

5.2、正则表达式的规则

  • “将小数点前面的值固定为 1 的正则表达式”。具体来讲,就是将二进制数表示的小数左移或右移(这里是逻辑移位。因为符号位是独立的)数次后,整数部分的第 1 位变为 1,第二位之后都变为 0(这样是为了消除第 2 位以上的数位)。而且,第 1 位的1 在实际的数据中不保存。由于第 1 位必须是 1,因此,省略该部分后就节省了一个数据位,从而也就可以表示更多的数据范围(虽不算太多)。下面一单精度浮点数举例;
    在这里插入图片描述
    双精度浮点数的表示方法也是如此,只是位数不同而已。

5.2、EXCESS 系统

  • EXCESS系统表现是指,通过将指数部分表示范围的中间值设为 0,使得负数不需要用符号来表示。也就是说,当指数部分是 8 位单精度浮点数时,最大值 11111111 = 255 的 1/2,即 01111111 = 127(小数部分舍弃)表示的是 0,指数部分是 11 位双精度浮点数时,11111111111 = 2047 的 1/2,即 01111111111 = 1023(小数部分舍弃)表示的是 0。指数部分中使用的 EXCESS 系统,使用这种方法主要是为了表示负数时不使用符号位。
    在这里插入图片描述
  • 十进制数 0.75 用单精度浮点数来表示就变成了0-01111110-10000000000000000000000。加入破折号(-)是为了区分符号部分、指数部分、尾数部分。这里,符号部分为 0,指数部分为 01111110,尾数部分为 10000000000000000000000。因为 0.75 是正数,所以符号位是 0。指数部分的 01111110 是十进制数 126用EXCESS 系统表现就是- 1(126- 127 =- 1)。根据正则表达式的规则,小数点前面的第 1 位是 1,因此尾数部分10000000000000000000000 实际上表示的是 1.10000000000000000000000 这个二进制数。将尾数部分的二进制数转换成十进制数,结果就是(1 × 2 的 0 次幂)+(1 × 2 的-1次幂)= 1.5。因此,0-01111110-10000000000000000000000 这个单精度浮点数,表示的就是“+ 1.5 × 2 的-1 次幂”。2 的-1 次幂是 0.5,+ 1.5 × 0.5 = + 0.75。正好吻合,结果正确。
    在这里插入图片描述
  • 但是通过该系统就会解决问题吗?答案显然是不可能的。接下来我们将处理,如何解决这些问题。

六、如何避免计算机计算出错

  • 计算机计算出错主要是因为数据溢出、浮点数参与计算等,在这里我们主要讲解浮点数运算出错的解决方案。

6.1、回避策略

  • 即无视这些错误。根据程序目的的不同,有时一些微小的偏差并不会造成什么问题。一般来讲,在科学技术计算领域,计算机的计算结果只要能得到近似值就足够了。那些微小的误差完全可以忽略掉。

6.2、将小数转化为整数

  • 刚开始讲过的将 0.1 相加 100 次这一计算,就可以转换为将 0.1 扩大 10 倍后再将 1 相加 100次的计算,最后把结果除以 10 就可以了。除此之外,BCD(Binary Coded Decimal)也是一种使用二进制表示十进制的方法。简单来讲,BCD 就是用 4 位来表示 0~9 的 1 位数字的处理方法,这里不再做详细说明。在涉及财务计算等不允许出现误差的情况下,一定要将小数转换成整数或者采用 BCD 方法,以确保最终得到准确的数值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值