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的Tornado框架异步编程入门实例
Apr 24 Python
Python的Tornado框架的异步任务与AsyncHTTPClient
Jun 27 Python
python实现求最长回文子串长度
Jan 22 Python
利用pandas将numpy数组导出生成excel的实例
Jun 14 Python
selenium+python设置爬虫代理IP的方法
Nov 29 Python
python顺序执行多个py文件的方法
Jun 29 Python
python实现的生成word文档功能示例
Aug 23 Python
python实现最大优先队列
Aug 29 Python
python递归下载文件夹下所有文件
Aug 31 Python
Python进阶学习之带你探寻Python类的鼻祖-元类
May 08 Python
将Python代码打包成.exe可执行文件的完整步骤
May 12 Python
OpenCV-Python实现怀旧滤镜与连环画滤镜
Jun 09 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
PHP中函数rand和mt_rand的区别比较
2012/12/26 PHP
CodeIgniter生成网站sitemap地图的方法
2013/11/13 PHP
php算法实例分享
2015/07/14 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
2019/03/11 PHP
php服务器的系统详解
2019/10/12 PHP
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
鼠标移动到图片名上,显示图片的简单实例
2013/07/14 Javascript
js和css写一个可以自动隐藏的悬浮框
2014/03/05 Javascript
js实现仿百度汽车频道选择汽车图片展示实例
2015/05/06 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
2016/12/08 Javascript
javascript 跨域问题以及解决办法
2017/07/17 Javascript
js原生实现移动端手指滑动轮播图效果的示例
2018/01/02 Javascript
js回溯法计算最佳旅行线路代码实例
2019/09/11 Javascript
JS中多层次排序算法的实现代码
2021/01/06 Javascript
Python多线程编程(六):可重入锁RLock
2015/04/05 Python
python将字符串转换成数组的方法
2015/04/29 Python
取numpy数组的某几行某几列方法
2018/04/03 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
python绘制漏斗图步骤详解
2019/03/04 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
对python 中class与变量的使用方法详解
2019/06/26 Python
Python中调用其他程序的方式详解
2019/08/06 Python
利用python list完成最简单的DB连接池方法
2019/08/09 Python
Flask框架实现的前端RSA加密与后端Python解密功能详解
2019/08/13 Python
解决python-docx打包之后找不到default.docx的问题
2020/02/13 Python
iPython pylab模式启动方式
2020/04/24 Python
Python函数的迭代器与生成器的示例代码
2020/06/18 Python
英国儿童鞋和靴子:Start-Rite
2019/05/06 全球购物
应聘自荐书
2013/10/08 职场文书
人民调解员先进事迹材料
2014/05/08 职场文书
关于环保的标语
2014/06/13 职场文书
公务员党员评议表自我鉴定
2014/09/14 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
浙江省杭州市平均工资标准是多少?
2019/07/09 职场文书
nginx请求限制配置方法
2021/07/09 Servers