- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
代码之谜谁偷了你的精度.doc
如果我告诉你,中关村配置最高的电子计算机的计算精度还不如一个便利店卖的手持计算器,你
一定会反驳我:又忘记吃药了吧
你可以用最主流的编程语言计算 0.2 + 0.4 ,如果你使用的是 Chrome、FireFox、IE 8+,可以按
F12 键,然后找到 「控制台」,输入上面的 表达式 0.2 + 0.4 ,回车。
然后再用最简陋的计算器(如果你没有手持计算器没关系,手机、电脑都自带一个计算器,打开
“运行”,输入calc ,回车) 再计算一下刚才的 算式 0.2 + 0.4。
怎么样?同意我的观点了吧! 再简陋的计算器也比超级计算器的精度高,关键不在于它的频率
和内存,而在于它是如何设计、如何表示、如何计算的。
不能表示 VS 不能精确表示
在上一章『浮点数(从惊讶到思考)』中我们讲到用浮点数表示 数 时出现的问题——很多数都 不
能表示。(注意 浮点数表示的是数,而不仅仅是小数。)
如果你数学比较好,或者你确信你身体健康,没有心脏病、高血压,没有受过重大精神创伤,那
我告诉你, 在浮点数的表示范围内,有多于 99.999…% 的数在计算机中是 不能表示 的。 真
的是太令人吃惊,也太令人遗憾了。 真相总是很残忍。
请注意我使用的措辞,区别开 不能表示 和 不能精确表示。
下面我从数量级分析一下,32bit 浮点数的表示范围是 10 的 38 次方,而表示个数呢,是 10 的
10 次方。 能够被表示的数只有 1/100000000…. (大概有30 个零),这个数多大呢?还记得
那个国际象棋和麦子的故事吗?
为了让你了解 指数的威力,我再举个例子:
有一张很大很大的纸,对折 38 次,会有多高呢? 一米?一百米?比珠峰还高?再次考验你心
脏承受能力的时刻到了:它不仅仅比珠峰高,其实它已经快到达月球了。
回到原来的话题,还有更残忍的真相。 在剩下的可以表示的不到 0.000…1% 的数中,又有多少
不能精确表示呢?这就是我写这篇博客的目的。
上一章中我还给出了一种用定点数精确表示小数的方法。 事实上,手持计算器、java 中的
BigDecimal、C# 中的货币类型、MySQL 中的 NUMERIC 类型就是这么干的。 你还记得在数据库
中添加字段时的 SQL 语句是如何写的吗?现在明白为什么我说 再简陋的计算器也比超级计算
器的精度高 了吧。
这篇博客我将为大家讲解为什么很多数 不能精确表示,本篇可能比较烧脑子,我会尽量用最通
俗的语言,最贴近现实的例子来讲解,不在乎篇幅有多长,关键是要给大家讲明白。下一篇,你
将了解到浮点数如何工作,以及为什么很多数 不能表示。
热身 —— 问:要把小数装入计算机,总共分几步?你猜对了,3 步。
· 第一步:转换成二进制
· 第二步:用二进制科学计算法表示
· 第三步:表示成 IEEE 754 形式
在上面的第一步和第三步都有可能 丢失精度。
十进制 VS 二进制
下面我们讨论如何把十进制小数转换成二进制小数(什么?你不会?请自觉去面壁)。
考虑我们将 1/7(七分之一) 写成小数的时候是如何做的?
用 1 除以 7,得到的商就是小数部分,剩下的余数我们继续除以 7,一直除到什么时候结束呢?
有两种情况:
1. 如果余数为 0。yeah!终于结束了,洗洗睡吧
2. 当除到某一步时,余数等于 1… 停!stop!等一下,我发现有什么地方怪怪的。余数
为 1,余数如果为 1 的话,再继续除下去,不就又是 1/7 了吗?绕了一个大弯,又回来了?
对,你猜的很对,它永远不会结束,它循环了。
注意我上面说的 情况2,我们判断他循环,并 不是从直观看感觉它重复了,而是因为在计算过
程中,它又回到了开头。为什么这么说呢?当你计算一个分数时,它总是连续出现 5,出现了
好多次,例如 0.5555555… 你也无法断定它是无限循环的,比如 一亿分之五。
记得高中时,从一本数学课外书学到了手动开平方的方法,于是很兴奋的去计算 2 的平方根,
发现它的前几位是 1.414,哇,原来「2 的平方根」等于 1.414141…。很多天以后,当我再次
看到我的笔记时,只能苦笑了,「2 的平方根」不可能循环啊,它可是一个无理数啊。
你可能不耐烦了,叽哩哇啦说这么多,有用吗?当然有用了,以后如果 MM 问你:你会爱我到什
么时候?你可以回答她:我会爱你到 1/7 的尽头。难道我会把我的表白方式告诉你们吗? 我对
你的爱就像圆周率,无限——却永不重复。
扯远了,现在会到主题。 你也许会说:我明白了,循环小数不能精确表示,放到计算机中会丢
失精度; 那么有限小数可以精确表示吧,比如 0.1。
对于无限小数,不只是计算机不能精确表示,即使你用别的办法(省略号除外),比如纸、黑板、
写字板…都无法精确表示。什么?手机?也不能,
文档评论(0)