Python浮点型(float)运算结果不正确的解决方案


Posted in Python onSeptember 22, 2020

一、问题说明

以前对浮点数运行没有没有太在意。昨天同事要求把百分比结果保存到文件上,然后就以保存1位小数的形式给他保存了。

但是今天同事运行时问能不能统一以一位小数的形式保存,当时觉得很奇怪昨天就是以一位小数形式存的怎么还会提这种要求呢。

其给回的截图确实是部分是一位小数的,但一部分是很长的。查看代码都统一如下格式:

# 使用round保留三位小数,然后乘以100,最后格式化为带百分号的字符串
rate=f"{round(x/y,3) * 100}%"

代码上没看出什么问题,直接运行确实是有些结果是一长串的。进行调试发现当x为37y为76时即会出现问题,如下图所示:

Python浮点型(float)运算结果不正确的解决方案

进行步骤拆分,发现round方法没有问题,问题在浮点数乘以100上(同时如下图可以看到也不是所有浮点数乘都有问题)

Python浮点型(float)运算结果不正确的解决方案

二、原因探究

搞不清原因,直到看到这篇文章:https://www.programiz.com/python-programming/numbers

大意是说二进制对很多浮点数无法准确表示只能用一个近似值代替,而当使用这些以近似值代替的浮点数进行进算时本质上是这些进似值参与了运算,出来的结果也就是进似值运算后的结果。

也就是说,一是这不是乘100的问题也不是乘法的问题而是整个浮点数运算都有问题,二是这不是python的问题是计算机浮点数存储的问题像C、Java等其他计算机语言进行运算都会有问题。

Python浮点型(float)运算结果不正确的解决方案

可能有人会疑惑:为什么二进制可以表示2不能表示0.2呢?

这是因为数值和字符串是不一样的,如果是字符串那么表示2.2点的左右两边的2编码是一样的就可以了(如ASCII码:504650),但数值不是这样,数值的整数部分和小数部分需要一个统一的表示形式,那就是加权位计数法。

整数部分都要以2的0次方(20)到2的无穷次方(2∞)表示,这没有问题,只要长度足够就能表示出所有奇数和偶数。2 = 1 * 21 + 0 * 20 = 10

小数部分都要以2的-1次方(2-1)到2的负无穷次方(2-∞)表示,这就有问题,因为比如2-1...2-∞不管怎么组合都不能完全等于0.2。0.2 = 0 * 2-1 + 0 * 2-2 + 1 * 2-3 ...

三、处理办法

这情况让我想起上份工作局方领导的一句话,应该是“可以理解但不能接受”。

原理上二进制无法精确表示一些浮点数可以理解,但是就这么返回个显然错误的结果给用户那是无法接受的。

python提供了Decimal()方法让浮点运算结果可以和人平时运算的结果一样。(Decimal本质应该还是通过加长长度提高精度)

Python浮点型(float)运算结果不正确的解决方案

# Decimal传字符串才能准确表示,所以需要先用str()把round()的结果转为字符串
rate=f"{Decimal(str(round(x/y,3))) * 100}%"

# 其实上边的结果出来是48.700%的形式,即三位小数的形式并不太符合我们保留一位小数的想法,真正符合想法得下面这样
# rate=f"{round(Decimal(str(round(x/y,3))) * 100, 1)}%"

# 其实我们说了这么多,我们都是建立在决定保留多少位再乘100这个前提下,倘若我们先乘100后决定保留几位那都不需要用Decimal
# rate=f"{round(x/y*100,1)}%"

Python浮点型(float)运算结果不正确的解决方案

参考:

https://www.programiz.com/python-programming/numbers

https://docs.python.org/3.7/library/decimal.html

以上就是Python浮点型(float)运算结果不正确的解决方案的详细内容,更多关于Python浮点型(float)运算结果不正确的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python编码时应该注意的几个情况
Mar 04 Python
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
Jul 18 Python
Python如何import文件夹下的文件(实现方法)
Jan 24 Python
Python cookbook(数据结构与算法)筛选及提取序列中元素的方法
Mar 19 Python
python中的字符串内部换行方法
Jul 19 Python
Python3.5以上版本lxml导入etree报错的解决方案
Jun 26 Python
python实现最大优先队列
Aug 29 Python
Python3如何对urllib和urllib2进行重构
Nov 25 Python
python实现飞船游戏的纵向移动
Apr 24 Python
从0到1使用python开发一个半自动答题小程序的实现
May 12 Python
python 贪心算法的实现
Sep 18 Python
使用Python将xmind脑图转成excel用例的实现代码(一)
Oct 12 Python
如何使用PyCharm引入需要使用的包的方法
Sep 22 #Python
python 如何区分return和yield
Sep 22 #Python
Python中三维坐标空间绘制的实现
Sep 22 #Python
Pyinstaller打包Scrapy项目的实现步骤
Sep 22 #Python
Python使用pickle进行序列化和反序列化的示例代码
Sep 22 #Python
Python如何获取文件路径/目录
Sep 22 #Python
JupyterNotebook 输出窗口的显示效果调整实现
Sep 22 #Python
You might like
国王的咖啡这么大来头,名字的由来是什么
2021/03/03 咖啡文化
用php或asp创建网页桌面快捷方式的代码
2010/03/23 PHP
Phpstorm+Xdebug断点调试PHP的方法
2018/05/14 PHP
JS写的数字拼图小游戏代码[学习参考]
2008/10/29 Javascript
JavaScript入门教程(8) Location地址对象
2009/01/31 Javascript
jQuery 常见开发使用技巧总结
2009/12/26 Javascript
EXTjs4.0的store的findRecord的BUG演示代码
2013/06/08 Javascript
Javascript Ajax异步读取RSS文档具体实现
2013/12/12 Javascript
AngularJs基于角色的前端访问控制的实现
2016/11/07 Javascript
js/jq仿window文件夹移动/剪切/复制等操作代码
2017/03/08 Javascript
微信、QQ、微博、Safari中使用js唤起App
2018/01/24 Javascript
vue2.0 better-scroll 实现移动端滑动的示例代码
2018/01/25 Javascript
JS如何获取地址栏的参数实例讲解
2018/10/06 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
2018/11/30 Javascript
vue中使用vue-cli接入融云实现即时通信
2019/04/19 Javascript
[40:13]Ti4 冒泡赛第二天 iG vs NEWBEE 2
2014/07/15 DOTA
在Django中同时使用多个配置文件的方法
2015/07/22 Python
python发送邮件实例分享
2017/07/28 Python
Python 和 JS 有哪些相同之处
2017/11/23 Python
python实现输入数字的连续加减方法
2018/06/22 Python
selenium python 实现基本自动化测试的示例代码
2019/02/25 Python
对Django 中request.get和request.post的区别详解
2019/08/12 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
python使用opencv resize图像不进行插值的操作
2020/07/05 Python
Pyecharts 中Geo函数常用参数的用法说明
2021/02/01 Python
科颜氏加拿大官方网站: Kiehl’s加拿大
2016/08/16 全球购物
在家更换处方镜片:Lensabl
2019/05/01 全球购物
软件工程师面试题
2012/06/25 面试题
营销与策划专业毕业生求职信
2013/11/01 职场文书
军训自我鉴定
2013/12/14 职场文书
硕士生工作推荐信
2014/03/07 职场文书
向领导表决心的话
2014/03/11 职场文书
2015年三万活动总结
2015/03/25 职场文书
实习单位意见
2015/06/04 职场文书
化工厂员工工作总结
2015/10/15 职场文书
2016年中秋节寄语大全
2015/12/07 职场文书