收录日期:2019/08/19 21:09:13 时间:2016/05/29 18:11:46 标签:脚本语言(Perl/Python)
python中的浮点运算误差很大,如何解决?是否有其它的类型替换浮点类型?
2.4中有decimal模块了专门进行这样的处理。
还有一个象 numpy这样的科学计算的包可以用吧。我没用过,不是很清楚。
我再说详细点:2.3*8 应等于18.4 ,但经过pythong计算后等于18.399999999999999

2.3中有没有解决办法,

to limodou:谢谢,我先down个2.4的看看
如果输出可以使用%.nf n表示小数位数与C一样 来控制精度
[Q]wrzcs:为什么会出现2.3*8=18.39999999999的情况?
是不是Python表示浮点数2.3存入内存的时候就不是2.3,而是一个相对接近的数?
这涉及到计算机内部浮点数表示的问题,好象是指数表示方法。具体地要查书了。
to limodou:
我查了一下书[1]。IEEE的标准是:一个机器数表示的不光是一个数,而且是在这个机器数
和最近的两个机器数半个区间内的所有数。
i.g.27.56640625这个数确实可以转换成一个64位的机器数,但是离这个机器数最近的
两个机器数却并不是简单的在最小位上做加减,而是跳过了很多中间的数。因此最后
那个表示27.56640625的机器数表示了这样一个区间里的所有数:
[27.5664062499999.......,27.5664062500000....)

这是最底的实现机制,但仍然不能解决Python为什么算出18.3999999来。简单的进位工作
是容易实现的,为什么Python不进位?我想Python一定引入了什么机制。你提到的numpy
我估计也最多是做了大数计算的模块,跟这个问题应该不相关。
[1]Richard L.Burden and J. Douglas Faires,Numerical Analysis(seventh edition),高教影印,2001
其实这只是Python在表示浮点数方面有些问题,内部它还是正确的:

>>> 2.3 * 8
18.399999999999999
>>> 2.3 *8 == 18.4
True
>>> 2.3 * 8 == 13.999999999999999999999999999999999999999999999999999999999
False
>>>
>>> 2.3 * 8
18.399999999999999
>>> 2.3 *8 == 18.4
True
>>> 2.3 * 8 == 18.399999999999999
True
>>>
真的唉,太荒唐了。

>>> 2.3 * 8
18.399999999999999
>>> 2.3 * 8 == 18.4
True
>>> 2.3 * 8 == 18.399999999999999
True
>>> 18.399999999999999 == 18.4
True
>>>
我觉得这个没有什么问题,
首先比较浮点数不推荐用==而是比较两数差的绝对值小于某个范围。
其次你找到的是一个特例,其实在其他语言中一样的有这样的问题,而且是当前计算机技术发展情况下不能完全解决的,所以在精确计算中很多时候是用的整数计算,最后转换成浮点数表示。
同意  xdspower()  观点
xdspower() wrote:
>首先比较浮点数不推荐用==而是比较两数差的绝对值小于某个范围。
我觉得Python的==绝对不是单纯的==,它一定是一个重构的运算符。也就是说,
如果在C语言里,我们要比较两个浮点数,大概都要先写一个常量(tolerant)来。
但应该在Python中有一个默认的tolerant,和基于它的一个==.
>而且是当前计算机技术发展情况下不能完全解决的
我天生愚笨弄不清楚这一点。比如2.3*8这个问题,计算机算出来的肯定不是18.4,而是
18.39999....;但另一方面,大家都知道2.3*8确实等于18.4,这才是一个精确的答案。
那么就应该在0.1上进位。而且这样一个功能也很好写出来啊。我确实不知道还有什么
理论背景。
TO oasis_me() :

计算机中的浮点数都只是近似值
Python 2.4的decimal就是解决这个问题的。

http://www.python.org/dev/doc/devel/whatsnew/node7.html
yep,2.4 should be the end of this story.The decision was to leave such a conversion out of the API.



oasis_me() 
>而且是当前计算机技术发展情况下不能完全解决的
我天生愚笨弄不清楚这一点。比如2.3*8这个问题,计算机算出来的肯定不是18.4,而是
18.39999....;但另一方面,大家都知道2.3*8确实等于18.4,这才是一个精确的答案。
那么就应该在0.1上进位。而且这样一个功能也很好写出来啊。我确实不知道还有什么
理论背景。
-----------------------------------------------
这和计算机中浮点数表示有关,在计算机中,所有的浮点数都不是精确表示,这也是不能直接比较浮点数是否相等的原因,你前面也提到了这点。但你主观的人为可以用简单进位来处理,这是不现实的,你怎么能确定一定是精确到0.1位上?为什么不能是0.01位或者0.001位?如果你自己的应用中需要确定,一般计算机上到是有专门的处理来满足你的要求,但从你前面的问题提出中你没有提到这点。而且这样的问题不但python中有,就是其他语言也一定存在,而且在理论上这样的处理是符合精度要求的,(18.4-18.399999999999999)=0.000000000000001啊。

怎样在ListView组件的详细显示模式下,让屏幕自动随输出数据滚屏和聚焦在输出的数据上面。 实现接口时出错,分数大大的有 《Delphi淡手辑略 之 数据库篇》:数据集解构成树(过程) 100分求教!!!文章“如何快速自动生成并定制报表”的问题!!! 一个农民上网的代价! 怎样将分割视图在一开始显示的时候就是确定的? Win2000server如何设置成路由器? 存储过程和函数得问题 转帖]!现在各大城市求爱对话写真 如何把XML+XSL的输出结果显示到一个指定的HTML元素里? 有些API中的参数开头是lpsz ,lpsa ....请问什么意思?相关的也说说好吗?谢谢 为何长语句分不了行 我用vs.net正式版开发的留言簿提供全部源码下载 公车上的性骚扰 请问哪里有比较好的关于 OpenGL 的网站或者是论坛啊?小弟的毕业设计课题是关于这个的!(NULL) 一个高难度的问题,特急! 在linux下有没有类似windows当中的dos95.BAT的文件 为什么在程序运行SQL中的存储过程,会出现未能找到存储过程...,可是我在SQL中有这个存储过程阿! 不晓得《资本论》的英文名字叫什么,特地来请教大家 一个高难度的问题,特急! 一个高难度的问题,特急! llpei 谢谢你。请进来领分。 这是VS.NET的BUG吗?不是该怎么解决? Slice(FSortArray^, FSize)解释解释“^”和“Slice()” 笑话:面条族大战完整篇(共42篇) 一个高难度的问题,特急! 关于日期问题请教 急急急急...!在线等待!救命呀!!!!解决问题送200分!!! 紧急求援:需要Fastreport 2.45的fr_class.pas文件,谁有? 这样的数组声明错在哪?