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

本文介绍了二进制数的基本概念,包括二进制数到十进制数的转换、二进制数的浮点数表示方法,以及计算机内部如何处理小数等问题。并探讨了计算机运算出错的原因及解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 热身

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

2 知识点

1. 计算机运算出错的原因是什么?

答:
- 有一些十进制数的小数是无法用二进制数来表示的!
- 首先,先明确,小数同样适用于位权的思想。小数后的数位的权依次为-1,-2,-3….

二进制数十进制数
0.00000
0.00010.0625
0.00100.125
0.00110.1857
0.01000.25
0.01010.3125

……
- 我们可以发现,当二进制的小数点是连续的时候,他对应的十进制的小数并不是连续的。所以,有很多十进制的小数是无法用二进制来表示的。这个时候,只能拓展二进制后小数的数位,比如,十进制的0.1,转换为二进制以后,就变成了0.00011001100…(1100不断循环出现)这样的循环小数,这根无法用十进制数来表示1/3是一样的道理。
- 所以,当要表示0.1的时候,用二进制来存储的话,只能是一个近似数,近似数的位数与存储0.1的空间(long,double)挂钩。

2. 计算机内部是如何表示小数的?

答:
- 首先需要明确的是,计算内部中是无法用1011.0011这样的带小数点的形式来表示小数的。
- 计算机中是使用浮点数来表示小数的。浮点类型一般有两种,分别是float(单精度浮点型,32位)和double(双精度浮点型,64位)。因为有位数的约束,所以肯定是有取值范围的!并且,在允许的取值范围中,肯定有一些循环小数是无法正确表示的。

3. 什么是浮点数?

答:是指用符号、尾数、基数、指数四个部分来表示小数。计算机使用二进制,所以基数是2,所以,实际的数据中可以不用考虑基数,只考虑符号、尾数、指数这三个部分即可表浮点数。形如:
+-m x n^e
其中,+-为符号,m为尾数,n为基数,e为指数。

4. 浮点数的表现方式?

答:一般使用IEEE(美国电气和电子工程师协会)的标准。IEEE的内部构造如下图所示:

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

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

符号部分,是使用一个数据位来表示数值符号,1表示负,0表示正。
尾数部分,用的是“将小数点前面的值固定为1的正则表达式”。
指数部分,用的是“EXCESS的系统表现”。

5. 计算机中小数点的正则表达式?

答:使用的是:将小数点前面的值固定为1的正则表达式。具体来说,就是将二进制表示的小数左移或者右移(逻辑位移)数次后,整数的第1位变成1,第1位之后(注意,是指整数部分的第2,3,4,5…位)的数位都变成0,并且,第1位在实际的数据中的不保存的。相当于节约了一个数位来保存数据,扩大了可以表示的数据范围。

单精度浮点数表示:

1011.0011                     ---原始数据
0001.0110011                  ---右移,使整数部分的第一位表成1,第一位之后的位数都变成0
0001.01100110000000000000000  ---确保小数点右边的长度为32位
01100110000000000000000       ---只保存小数点后部分
6.EXCESS系统是啥?

答:EXCESS系统,是同时存储正数和负数的一种方式。简单来说,将表示范围的中间值设置为0,使得负数不需要用符号来表示。
单精度浮点(32位)指数部分的系统表现:
float中指数部分占8位,所以可以表示2的8次方=255;
取中间的数127,把他当做0;那么:

实际的值(二进制)实际的值(十进制)EXCESS系统表现(十进制)
11111111255128(=255-127)
11111110254127(=254-127)
011111111270(=127-127)
000000000-127(=0-127)
7.正则表达式与EXCESS系统的结合?

答:十进制数0.75在计算机中float表示为

0-01111110-10000000000000000000000
其中,
符号位0,表示是正数;
指数部分01111110,转化为十进制是126,EXCESS系统表现为126-127=-1;
尾数部分10000000000000000000000,表示二进制数1.10000000000000000000000(因为0.1默认是不保存,尾数部分只存了1.以后的部分);
所以,用二进制数表示为1.1x2^(-1),
用十进制表示位1.5x2^(-1) = 0.75;

需要注意的是,在转换的过程中,指数是多少,是根据将尾数部分位移的过程中确定的,左移,则表示是2的负数次方,右移,表示2的正数次方。移动了多少位,则表示指数的绝对值是多少。

8.十进制数转二进制数的方法

答:整数、小数部分单独转换。
- 整数部分:整数部分不断除以2,直到为0,得到的余数逆序排列;
- 小数部分:小数部分不断乘以2,直到为0,直到为0,将乘积中得整数部分顺序排列。

9. 如何避免计算机计算出错?

答:出错的原因显而易见。两种情况:一种是采用了浮点数来处理小数,一种是位溢出。这里只讨论浮点数导致的错误。
解决方案:
- 回避策略:无视错误,工程计算中,一些误差是可以忽略的。
- 转换为整数计算:将小数转换为整数来计算。java中的BigDecimal就是采用这种方法。
- BCD。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值