python 浮点数四舍五入需要注意的地方


Posted in Python onAugust 18, 2020

本文主要分享基于python的数据分析三方库pandas,numpy的一次爬坑经历,发现并分析了python语言对于浮点数精度处理不准确的问题,并在最后给出合理的解决方案。如果你也在用python处理数据,建议看一下,毕竟0.1的误差都可能造成比较大的影响。

问题出现

早上到了公司,领导发了几个文件过来,说这两天测试环境跑出来的数据,与实际情况有所出入,看看哪出的问题,尽快解决···

开始排查

先对比数据,发现并不是所有的数据都出现问题,只有10%左右的数据有这个问题,说明应该不是逻辑上的问题,初步判断可能为个别情况需要特殊处理,考虑不周导致
检查梳理各个运算模块,用debug断点调试一波,确定了数据出现偏差的模块
通过单独测试这个单元模块最终确定,涉及到两数相除结果为0.5(浮点数)的地方有问题
预期结果:np.round(0.5)=1,实际运算结果:np.round(0.5)=0,于是我做了如下的试验

# 基于python3.7版本 
>>> import numpy as np 
 
# 先看看 0 < x < 1 这个范围的结果,发现有问题 
>>> np.round(0.50) 
0.0 
>>> np.round(0.51) 
1.0 
>>> np.round(0.49) 
0.0 
 
# 我担心是不是只有小数点为.5的都会呈现这种问题,所以测试了 x > 1的结果,发现还是有问题 
>>> np.round(1.5) 
2.0 
>>> np.round(2.5) 
2.0 
>>> np.round(3.5) 
4.0 
>>> np.round(4.5) 
4.0

通过对比,发现确实涉及到.5的值会有些和预想的不同,看看啥原因

分析问题

确实发现了关于浮点数(.5出现了理解上的偏差),看看官方文档怎么解释这个现象

numpy.around(a, decimals=0, out=None)[source]
Evenly round to the given number of decimals.

# 对于恰好介于四舍五入的十进制值之间的中间值(.5),NumPy会四舍五入为最接近的偶数值。
# 因此1.5和2.5四舍五入为2.0,-0.5和0.5四舍五入为0.0,依此类推。
For values exactly halfway between rounded decimal values,
NumPy rounds to the nearest even value.
Thus 1.5 and 2.5 round to 2.0, -0.5 and 0.5 round to 0.0, etc.

# np.around使用快速但有时不精确的算法来舍入浮点数据类型。
# 对于正小数,它等效于np.true_divide(np.rint(a * 10 **小数),10 **小数),
# 由于IEEE浮点标准[1]和 十次方缩放时引入的错误
np.around uses a fast but sometimes inexact algorithm to round floating-point datatypes.
For positive decimals it is equivalent to np.true_divide(np.rint(a * 10**decimals), 10**decimals),
which has error due to the inexact representation of decimal fractions in the IEEE floating point standard [1]
and errors introduced when scaling by powers of ten

  • 其实也就是说:对于带有.5这种刚好介于中间的值,返回的是相邻的偶数值
  • 白话解释:如果一个数字带有浮点数(.5),整数部分为偶数,则返回这个偶数;整数部分奇数,则返回这个奇数+1的偶数
  • 规律解释:如果整数部分能够整除2,则返回整数部分;如果整数部分不能整除2,则返回整数部分 +1

解决问题

先不做任何改动,看下数据误差的情形

# 我们为了先看下现象,构造如下案例 
import pandas as pd 
import numpy as np 
 
df = pd.DataFrame({"num1": [1, 1, 1.5, 5, 7.5], "num2": [2, 3, 1, 6, 3]}) 
 
df["真实值"] = df["num1"] / df["num2"] 
# 看下round函数过后的结果 
df["偏差值"] = np.round(df["num1"] / df["num2"])

原始结果图片如下

python 浮点数四舍五入需要注意的地方

不做处理,期望值和偏差值不等的情况出现

我的解决方案

  • 我根据我的精度要求,构建精度范围所需要保留的小数点的最后一位,通过这个数字是否为5,判断是否需要向上取整
  • 举例来说,本案例中我只需要保留整数部分的数据,那么我只需要确定小数点后第一位是否是数字5就可以了

上代码

import pandas as pd 
import numpy as np 
import math 
 
df = pd.DataFrame({"除数": [1, 1, 1.5, 5, 7.5], "被除数": [2, 3, 1, 6, 3]}) 
 
# 记录真实值 
df["真实值"] = df["除数"] / df["被除数"] 
 
# 记录整数部分 
df["辅助整数列"] = df["真实值"].apply(lambda x: math.modf(x)[1]) 
 
# 记录小数部分,因为我的最后结果精度为只保留整数部分,所以我只需要保留一个小数点位进行判断是否需要进位操作 
df["辅助小数列"] = df["真实值"].apply(lambda x: str(math.modf(x)[0]).split(".")[1][0]) 
 
# 小数点后的第一位是为5,则向上取整,不是5则调用原np.round就行了 
df["期望值修正"] = df.apply(lambda x: x.辅助整数列 + 1 if (x.辅助小数列 == "5") else np.round(x.真实值), axis=1)

结果如下所示

python 浮点数四舍五入需要注意的地方

以上就是python 四舍五入需要注意的地方的详细内容,更多关于python 四舍五入的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python的内存泄漏及gc模块的使用分析
Jul 16 Python
python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)
Aug 25 Python
用Python遍历C盘dll文件的方法
May 06 Python
python监控文件或目录变化
Jun 07 Python
全面了解python字符串和字典
Jul 07 Python
解决Python3中的中文字符编码的问题
Jul 18 Python
对pandas里的loc并列条件索引的实例讲解
Nov 15 Python
python matplotlib如何给图中的点加标签
Nov 14 Python
pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程详解
Jan 02 Python
TensorFlow Autodiff自动微分详解
Jul 06 Python
python实现粒子群算法
Oct 15 Python
matplotlib部件之套索Lasso的使用
Feb 24 Python
Python filter过滤器原理及实例应用
Aug 18 #Python
Python lambda表达式原理及用法解析
Aug 18 #Python
python 使用建议与技巧分享(四)
Aug 18 #Python
Python正则re模块使用步骤及原理解析
Aug 18 #Python
python使用建议技巧分享(三)
Aug 18 #Python
python3跳出一个循环的实例操作
Aug 18 #Python
OpenCV图片漫画效果的实现示例
Aug 18 #Python
You might like
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
dedecms采集中可以过滤多行代码的正则表达式
2007/03/17 PHP
php动态变量定义及使用
2015/06/10 PHP
phpmyadmin下载、安装、配置教程
2017/05/16 PHP
PHP设计模式之委托模式定义与用法简单示例
2018/08/13 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
PHP 枚举类型的管理与设计知识点总结
2020/02/13 PHP
jQuery ReferenceError: $ is not defined 错误的处理办法
2013/05/10 Javascript
javascript获得当前的信息的一些常用命令
2015/02/25 Javascript
JS中SetTimeout和SetInterval使用初探
2017/03/23 Javascript
ES6新特性之类(Class)和继承(Extends)相关概念与用法分析
2017/05/24 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
2017/09/26 Javascript
详解vue.js下引入百度地图jsApi的两种方法
2018/07/27 Javascript
创建echart多个联动的示例代码
2018/11/23 Javascript
ES6的解构赋值实例详解
2019/05/06 Javascript
浅谈v-for 和 v-if 并用时筛选条件方法
2019/11/07 Javascript
浅谈Node新版本13.2.0正式支持ES Modules特性
2019/11/25 Javascript
原生JavaScript实现换肤
2021/02/19 Javascript
[02:16]卖萌的僵尸 DOTA2神话信使飞僵小宝来袭
2014/03/24 DOTA
[03:22]DAC最前线(第二期)—DOTA2亚洲邀请赛主赛场周边及线路探访
2015/01/24 DOTA
[00:33]DOTA2上海特级锦标赛 CDEC战队宣传片
2016/03/04 DOTA
[08:47]2018国际邀请赛 OG战队举杯时刻
2018/08/29 DOTA
python实现将元祖转换成数组的方法
2015/05/04 Python
在Django的URLconf中使用多个视图前缀的方法
2015/07/18 Python
python使用邻接矩阵构造图代码示例
2017/11/10 Python
解读! Python在人工智能中的作用
2017/11/14 Python
TensorFlow 滑动平均的示例代码
2018/06/19 Python
Python爬虫之pandas基本安装与使用方法示例
2018/08/08 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
解决Python logging模块无法正常输出日志的问题
2020/02/21 Python
jupyter notebook的安装与使用详解
2020/05/18 Python
浅谈pandas dataframe对除数是零的处理
2020/07/20 Python
Python制作运行进度条的实现效果(代码运行不无聊)
2021/02/24 Python
一年级学生期末评语
2014/04/21 职场文书
2015年教务工作总结
2015/05/23 职场文书