浮点数精确运算.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
浮点数精确运算

1.01 + 2.01 = 3.02 2.01 * 2.01 = 4 0401 不知你注意没有,这个很寻常的等式,你如果将它放在C++中,Java中,Basic中,它居然是不成立的。计算机在开玩笑吗?噢,对了,隐约记得这好象是浮点数的问题,似乎很多很多年前,老师说过。还有某位姓林的先生在某本书里提过=0的判断。嗯,如果你不遇到此问题,那你完全可以把它抛到火星上去,可惜,偶不好彩,这样的问题,被俺遇到了。唉! why?how? 没办法,硬着头皮,从头开始。 一:为何不成立?Why? 这得从浮点数的在计算机内的存储开始说起,我这里闲话少说。我们只谈双精度double数(至于float,基本上是五十步和一百步的区别)。 双精度数在计算机内的表示方式是:(三部分组成) 符号(正或负) 阶码(2的N次幂) 尾数(大于等于1小于2的数) 比如: -(符号) 1.01(尾数) * 2~1(N = 1) = - 2.02 具体到计算机的存储单元:双精度数共占8字节(64bit) 符号位(占1个bit) 阶码(11个bit) 尾数(52个bit) 解释一下: 符号位:0表示正 1表示负 阶码:是一个偏移量,1023的偏移量,它的1023相当于0,小于1023时为负, 大于1023时为正,如:10000000001表示指数为1025 - 1023 = 2,表示真值为2^2。 好了,知道了原理,我们开始分析上述等式为何为不等。 (相应数的存储值,可以简单用C语言的指针方式取出) 1.01 表示为: 0 0111111 1111 0000111101011000111100101001 2.01 表示为; 0 1000000 0000 0000011110100100011100010100 3.02 表示为: 0 1000000 0000 1000111101011000111100101001 2.01+1.01 在编程语言中的计算结果 表示为: 0 1000000 0000 1000111101011000111100101000 好了,我们可以比较一下3.02和计算结果,果然有所不同,只不过最后一个bit不同嘿。 为了验证一下,可以用手工计算一下2.01+1.01: 先把1.01的幂次变为1(与2.01的阶码相同),于是,将尾数右移一位。得到: 10000111101001000111000101001 加上2.01的尾数。 0000011110100100011100010100 得到: 1000111101011000111100101000 嗯,与计算机的计算结果相同,我们的运算思路是正确的。 因此,结论出来了,因为浮点数在计算机内的存储存在偏差,导致运算时,与实际期望的结果不同。很多时候,你可以不理它,但是,可以肯定负责任的说,发射卫星的运算时,你需要知道,否则,卫星一转眼就不见了。 二:不成立的的原因找到了,那怎么解决这个问题呢,How? 一个简单的解决办法是: 不要用浮点数来存储浮点,对于VC,Java,Basic,最好的办法是用Decimal来保存它。 下面是分别的实现:(以加法为例,其它四则运算处理相同) VC中: double doublAdd(double dbl1, double dbl2) { double dblResult; DECIMAL dec1,dec2,decResult; ::VarDecFromR8(dbl1,dec1); ::VarDecFromR8(dbl2,dec2); ::VarDecAdd(dec1,dec2,decResult); ::VarR8FromDec(decResult,dblResult); return dblResult; } VB中: Private Function doubleAdd(ByVal dbl1 As Double, ByVal dbl2 As Double) As Double doubleAdd = CDec(dbl1) + CDec(dbl2) End Fu

文档评论(0)

sy78219 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档