深入浅出计算机组成原理
徐文浩
bothub 创始人
70432 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 62 讲
深入浅出计算机组成原理
15
15
1.0x
00:00/00:00
登录|注册

15 | 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?

课后思考
推荐阅读
总结延伸
浮点数的表示
定点数的表示
浮点数的不精确性
浮点数和定点数

该思维导图由 AI 生成,仅供参考

在我们日常的程序开发中,不只会用到整数。更多情况下,我们用到的都是实数。比如,我们开发一个电商 App,商品的价格常常会是 9 块 9;再比如,现在流行的深度学习算法,对应的机器学习里的模型里的各个权重也都是 1.23 这样的数。可以说,在实际的应用过程中,这些有零有整的实数,是和整数同样常用的数据类型,我们也需要考虑到。

浮点数的不精确性

那么,我们能不能用二进制表示所有的实数,然后在二进制下计算它的加减乘除呢?先不着急,我们从一个有意思的小案例来看。
你可以在 Linux 下打开 Python 的命令行 Console,也可以在 Chrome 浏览器里面通过开发者工具,打开浏览器里的 Console,在里面输入“0.3 + 0.6”,然后看看你会得到一个什么样的结果。
>>> 0.3 + 0.6
0.8999999999999999
不知道你有没有大吃一惊,这么简单的一个加法,无论是在 Python 还是在 JavaScript 里面,算出来的结果居然不是准确的 0.9,而是 0.8999999999999999 这么个结果。这是为什么呢?
在回答为什么之前,我们先来想一个更抽象的问题。通过前面的这么多讲,你应该知道我们现在用的计算机通常用 16/32 个比特(bit)来表示一个数。那我问你,我们用 32 个比特,能够表示所有实数吗?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

浮点数和定点数是计算机中表示实数的两种方式。浮点数通过科学计数法表示实数,能够表示较大范围的数值,但存在精度问题;而定点数将整数和小数部分分开表示,适用于需要精确表示小数的场景,但表示范围有限。本文介绍了两种表示方式的特点及在计算机中的应用。浮点数能够表示的数据范围较大,因为其小数点位置是“浮动”的,而定点数则将小数点固定在某一位。浮点数无法精确表示某些数值,导致近似计算,因此在使用过程中会遇到一些问题。读者可以通过对比两种表示方式的优缺点,更好地理解在实际应用中如何选择合适的表示方式来处理实数数据。文章提到了浮点数计算中的各种“坑”,并推荐了相关阅读材料。文章还提出了课后思考问题,鼓励读者参与讨论。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入浅出计算机组成原理》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(59)

  • 最新
  • 精选
  • lzhao
    在这样的浮点数表示下,不考虑符号的话,浮点数能够表示的最小的数和最大的数,差不多是 1.17×10−381.17×10−38 和 3.40×10383.40×1038。比前面的 BCD 编码能够表示的范围大多了 这个范围怎么得来的

    作者回复: 最大的数,会是小数位全部为1,指数位二进制表示成127 表示成二进制就是 1.11111... ^(2^127) 差不多就是1.9999999 ^(2^127) 差不多正好是 3.4028235 x (10 ^ 38) 最小的数就是 1.000..... ^ (2^-126) 差不多就是 1.0000 ^ (2^-126) 差不多正好就是 1.17549435 x (10^-38)

    2019-05-29
    7
    59
  • 小崔
    对于0.5,按照老师的说法,可以用s = 0、e = -1、f = 0来表示。 但是对照表格,似乎s = 0、e = 0、f = 5也可以表示?请解惑

    作者回复: s = 0, e = 0 的时候,无论 f 是多少,都是表示浮点数 0 f = 5,底数是1.5 而不是 0.5

    2019-05-29
    14
    28
  • 陆离
    如果觉得没有理解老师讲的可以参考阮一峰的一篇文章 http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

    作者回复: 👍 其实这一讲还有下篇,具体s, e, f怎么计算大家可以看一下周五的下篇,以及里面给的交互演示网页。

    2019-05-29
    2
    13
  • 愤怒的虾干
    老师,我在java里验证了下,譬如1.9999999f,小数点后的位数,即“9999999”七个9是没办法用8个bit位表示的,我猜测会失去精度变成2.0f,但是调用Float.toHexString发现是0x1.fffffep0,fffffe怎么看都不可能是9999999。于是我换了个数1.5f,16进制浮点数表示为0x1.8p0,可以看到小数点后是8,16进制的一半。这样看的话,上面的小数部分十进制显示是:fffffe/2^23 = 0.9999999,加上小数点前的1就是1.9999999了。 根据这个思路可以推算出规则浮点数最小1.0*2^(-126),最大(1 + (2^23 - 1)/2^23)*2^(127)

    作者回复: 愤怒的虾干同学你好, toHexString表示的是把10进制转换成16进制表示。 0.9999999的小数部分转换成16进制,采用的是 乘以2 然后如果大于1去减1这样的操作过程。你试一下就知道就会是1111111...因为一共有23位长,所以最后有一位可能是0,所以就是 fffffe,就是表示0.999999 以1.5f为例,小数部分是0.5 乘以2就是1.0,减1就是0 那么0.5表示成2进制就是 0.1000000 4位表示1个16进制数第一位就是8,后面都是0会截断显示。 你可以照着接下来第16讲的转换过程试一下,看看小数部分会变成什么样子。 然后把二进制转换成16进制,就能知道为什么了。

    2019-05-29
    7
  • 古夜
    对于那个公式,底数怎么表示?32位都给了符号位,指数位,小数位,底数怎么办?

    作者回复: 底数就是 1.小数位,也就是1.f。因为是二进制,所以底数的“整数”部分可以认为必然是1啊,不存在其他情况

    2019-05-29
    7
  • humor
    如果7位表示0-99的话,32位的取值范围是0-9999999.99。如果需要负数,第一位表示符号位,取值范围是-7999999.99-7999999.99

    作者回复: 👍

    2019-05-29
    6
  • 任雪龙
    老师,感觉今天这个讲的太粗糙了,很多东西都是用结果解释结果,比如对 0.5 这个数 s 、e、f 的值,值是从哪里推导得来的都没有解释,希望可以详细解释下

    作者回复: 任雪龙同学你好, 这个在第16讲里面会讲解一下计算过程,因为一讲的篇幅有限,所以没有放在15讲里面讲完。

    2019-05-29
    5
  • 88591
    老师,为什么公式定义是 s x 1.f x 2e ,不是s x 2ex 1.f (这种方式更容易对应位数 :符号位,指数位,有效位数)。

    作者回复: loser同学, 你好,这个我的确也不知道,有兴趣大家可以一起来考古一下。

    2019-12-09
    1
  • Only now
    IEEE754?

    作者回复: 对,整个是浮点数的标准 https://zh.wikipedia.org/zh-hans/IEEE_754

    2019-05-29
    1
  • 鱼向北游
    老师可以扩展讲一下 移码 毕竟阶码部分并不是我们常见的原码或者补码 也不是移码的常见表示 还有非规格化表示法的由来

    作者回复: 这个想法不错,我看是否搞一章加餐

    2019-05-29
    1
收起评论
显示
设置
留言
59
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部