收录日期:2019/04/24 08:49:11 时间: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啊。

前些时候的一个动态刷新节点的树 招聘.net(c#,vb.net,asp.net)开发人员——帮公司发个招聘,15天内有效!!! 初次编写函数,不起作用,请帮忙看一下 关于 CPropertyPage的问题 请各位高手说一下怎么模拟鼠标移动?C++Builder Hibernate中的综合查询问题 为什么插入的clob出现value error? 写文件速度问题,在线等,马上给分 为什么发不了邮件?一段简单的代码 启动不了了 急急急 高分送 oracle9.2.0.1中blob数据操作问题 从崇祯说管理 初学COM+,有一个关于远程COM+组件和本地activex(客户端)上的疑问,请大家帮帮我!谢谢!!! 请教在bird(波导)工作的朋友,多谢 AfxBeginThread建立线程错误 ,怎么解决? 欲分析内核先作什么 谁知道wros.exe这个进程是什么东西 串口通信问题,碰到字节 $00 就停止接收字符了??? 浙江省今年的成绩出来的了? 往ifram里写数据是说没有权限,我要怎么改? 初学者的困惑! 谁有不看的《javascript宝典》,卖给我吧。 刚接触SQL!请帮忙。。。。。 我想打开一个非模态对话框,打开该对话框后,如果鼠标直接移开对话框会出现程序错误。但是用鼠标点击一下后再移开就没有这个问题了。 datagrid的问题 我的apache2.0.48无法显示中文怎么办?? 十万火急 我的新主页,主要是为了找工作用的,请大家PP linux学习 哪位大侠知道WinRunner的Java插件在哪里可以下载?