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生成随机数的方法
Jan 14 Python
python字典操作实例详解
Nov 16 Python
Python进阶之尾递归的用法实例
Jan 31 Python
Python中property属性实例解析
Feb 10 Python
Python 实现异步调用函数的示例讲解
Oct 14 Python
pyshp创建shp点文件的方法
Dec 31 Python
在Python 字典中一键对应多个值的实例
Feb 03 Python
复化梯形求积分实例——用Python进行数值计算
Nov 20 Python
Pytorch Tensor基本数学运算详解
Dec 30 Python
tensorflow 只恢复部分模型参数的实例
Jan 06 Python
什么是python的id函数
Jun 11 Python
python获取整个网页源码的方法
Aug 03 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代码把全角数字转为半角数字
2007/12/10 PHP
PHP输入流php://input介绍
2012/09/18 PHP
php创建基本身份认证站点的方法详解
2013/06/08 PHP
使用HMAC-SHA1签名方法详解
2013/06/26 PHP
PHP下获取上个月、下个月、本月的日期(strtotime,date)
2014/02/02 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
Redis构建分布式锁
2017/03/28 PHP
css动画效果之animation的常用样式
2021/03/09 HTML / CSS
js更优雅的兼容
2010/08/12 Javascript
JavaScript类型转换方法及需要注意的问题小结(挺全面)
2010/11/11 Javascript
8个超棒的学习 jQuery 的网站 推荐收藏
2011/04/02 Javascript
用jquery实现自定义风格的滑动条实现代码
2011/04/26 Javascript
jquery 事件冒泡的介绍以及如何阻止事件冒泡
2012/12/25 Javascript
javascript将数组插入到另一个数组中的代码
2013/01/10 Javascript
js 自定义个性下拉选择框示例
2013/08/20 Javascript
Node.js的特点和应用场景介绍
2014/11/04 Javascript
如何用angularjs制作一个完整的表格
2016/01/21 Javascript
利用JS提交表单的几种方法和验证(必看篇)
2016/09/17 Javascript
在Create React App中启用Sass和Less的方法示例
2019/01/16 Javascript
JavaScript禁用右键单击优缺点分析
2019/01/20 Javascript
详解Element-UI中上传的文件前端处理
2019/08/07 Javascript
[06:09]辉夜杯主赛事开幕式
2015/12/25 DOTA
Python对列表中的各项进行关联详解
2017/08/15 Python
numpy.linspace 生成等差数组的方法
2018/07/02 Python
python使用pipeline批量读写redis的方法
2019/02/18 Python
Python分析彩票记录并预测中奖号码过程详解
2019/07/09 Python
Python识别快递条形码及Tesseract-OCR使用详解
2019/07/15 Python
Django对接支付宝实现支付宝充值金币功能示例
2019/12/17 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
2020/01/08 Python
Python Selenium自动化获取页面信息的方法
2020/08/31 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
2021/01/27 Python
英国文胸专家:AmpleBosom.com
2018/02/06 全球购物
体育专业个人求职信范文
2013/12/27 职场文书
求职信范文英文版
2014/01/05 职场文书
幼儿园安全检查制度
2014/01/30 职场文书
2016年学校“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书