首页 > 其他分享 >精度溢出问题

精度溢出问题

时间:2023-04-11 09:45:00浏览次数:37  
标签:9353 366cf056 11ed time 99e44f95bc32 问题 溢出 0f9b 精度

背景

python中定义好的浮点型数据,在实际业务系统传输过程中,出现了精度溢出的问题。具体实例如下:

加载数据

import numpy as np
import pandas as  pd


#加载本地的测试数据
data_path=r'D:\desktop\data_b6da1bdd4fa54677a03994e0db9fb508.csv'
data=pd.read_csv(data_path)
data.head()
"""
	time	366cf056-0f9b-11ed-9353-99e44f95bc32
0	0.0	0.066
1	0.2	0.052
2	0.5	0.023
3	0.8	0.006
4	1.0	0.004

"""

查看数据基础属性


data.info()#查看数据的基础信息
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2049 entries, 0 to 2048
Data columns (total 2 columns):
 #   Column                                Non-Null Count  Dtype  
---  ------                                --------------  -----  
 0   time                                  2049 non-null   float64
 1   366cf056-0f9b-11ed-9353-99e44f95bc32  2049 non-null   float64
dtypes: float64(2)
memory usage: 32.1 KB

"""

业务应用:将dataframe转换成json

def dataframe_to_json(raw_data):
    """将dataframe转换成json的形式"""
    data = raw_data.values.tolist()
    cols = raw_data.columns.tolist()
    output = list(map(lambda x: dict(zip(cols, x)), data))
    return output
dataframe_to_json(data)[:10]#查看前10个
"""
[{'time': 0.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.066},
 {'time': 0.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.052},
 {'time': 0.5, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.023},
 {'time': 0.8, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.006},
 {'time': 1.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.004},
 {'time': 1.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.009},
 {'time': 1.5, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.003},
 {'time': 1.8, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.002},
 {'time': 2.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.002},
 {'time': 2.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.003}]
"""

在jupyter或pycharm本地测试中显示没有任何问题,但是嵌入到开发的软件中,以exe的方式运行时,过程中偶尔传输的结果是:

#相同的python虚拟环境,相同的数据,在实际项目过程中运行的结果:
[{'time': 0.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.06599999964237213}, {'time': 0.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.052000001072883606}, {'time': 0.5, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.023000000044703484}, {'time': 0.8, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.006000000052154064}, {'time': 1.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.004000000189989805}, {'time': 1.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.008999999612569809}, {'time': 1.5, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.003000000026077032}, {'time': 1.8, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.0020000000949949026}, {'time': 2.0, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.0020000000949949026}, {'time': 2.2, '366cf056-0f9b-11ed-9353-99e44f95bc32': 0.003000000026077032}]

问题定位

与python中浮点数据的表示机制有关

相关文档说明

在stackflow(https://stackoverflow.com/questions/31977319/floating-point-precision-affected-when-converting-dataframe-to-list)上 我也查到了类似的问题,大家给到核心建议是使用"round"方法。

查看python官方文档关于《浮点算术:问题和限制》(https://docs.python.org/3.8/tutorial/floatingpoint.html)的相关说明:

核心说明

核心的说明有以下几点:

  1. 浮点数在计算机硬件中表示为以 2 为底的(二进制)分数。
  2. 不幸的是,大多数十进制分数不能完全表示为二进制分数。结果是,通常,您输入的十进制浮点数仅与实际存储在机器中的二进制浮点数近似。
  3. Python 只打印机器存储的二进制近似值的真实十进制值的十进制近似值。
  4. 有趣的是,有许多不同的十进制数共享相同的最接近的近似二进制分数。
  5. 请注意,这是二进制浮点的本质:这不是 Python 中的错误,也不是您的代码中的错误。您将在所有支持硬件浮点运算的语言中看到相同的内容(尽管某些语言默认或在所有输出模式下可能不会显示差异)。
  6. 表示错误问题:指某些(实际上是大多数)十进制分数不能完全表示为二进制(以 2 为底)分数的事实。这就是为什么 Python(或 Perl、C、C++、Java、Fortran 和许多其他语言)通常不会显示您期望的确切十进制数的主要原因。 这是为什么?1/10 不能完全表示为二进制分数。今天(2000 年 11 月)几乎所有机器都使用 IEEE-754 浮点运算,并且几乎所有平台都将 Python 浮点数映射到 IEEE-754 “双精度”。754 个双精度数包含 53 位精度,因此在输入时,计算机会努力将 0.1 转换为最接近的小数,其形式为J /2** N,其中J是正好包含 53 位的整数。

解决方案

  • 使用format格式化输出(或f-string )
  • 保存成分数的形式
#应用示意
format(math.pi, '.12g') #'3.14159265359'

#转化成分数
x=3.14159
x.as_integer_ratio()#转换成对应的分数表示
"""
(3537115888337719, 1125899906842624)#分子/分母
"""
x=0.25
x.as_integer_ratio()
"""
(1, 4)##分子/分母
"""


from decimal import Decimal
Decimal.from_float(0.1)
"""
Decimal('0.1000000000000000055511151231257827021181583404541015625')
"""
format(Decimal.from_float(0.1),".17")#'0.10000000000000001'

from fractions import Fraction
Fraction.from_float(0.1)
(0.1).as_integer_ratio()
"""
(3602879701896397, 36028797018963968)
"""

回归上述问题

但针对背景中提到的问题,我们可以看到输出的数据都是数值型,通过上述格式化方案或分数不足以解决问题。最红通过定位发现dataframe.values.tolist()中才会出现该问题。

在dataframe结果时我们我们已经明确指定小数位数,但是通过dataframe.values.tolist()方法或者dataframe.values时会出现精度溢出的问题。 分析: 基于python中float型数据的保存机制,精度溢出是随机的,完全依赖于当前运行环境。 精度溢出以外的数据对我们的影响有两种情况:

第一种:通过保留小数(round),我们可以达到目标预期;

第二种:通过保留小数后的数值与我们的实际预期差异较大,这种可能性非常小。

解决方案: 本文给出一种结合业务场景的"round"方法,假定我们保存的结果数据可能有3位小数也可能包含6位小数,此时我们通过使用np.allclose()函数 比较误差,以此确定保留几位小数。以此减少精度溢出问题对我们的影响。

#代码优化形式
def dataframe_to_json(raw_data):
    """将dataframe转换成json的形式"""
    data = raw_data.values  # .tolist()
    cols = raw_data.columns  # .tolist()
    try:
        data1 = np.round(data, 3)
        data2 = np.round(data, 6)
        data = data1 if np.allclose(data1, data) else data2
    except Exception:
        pass
    output = list(map(lambda x: dict(zip(cols, x)), data))
    return output

标签:9353,366cf056,11ed,time,99e44f95bc32,问题,溢出,0f9b,精度
From: https://www.cnblogs.com/AzeHan/p/17305094.html

相关文章

  • selenium驱动未随浏览器更新而同步更新的问题
    基于selenium模拟谷歌浏览器登录时,依赖chromedriver.exe版本信息。但谷歌浏览器升级后,之前创建的脚本可能会出现因驱动版本过低,使得之前创建的脚本运行失败的问题。下面针对该问题进行探索和解决。selenium版本importseleniumselenium.__version__#'4.7.2'获取谷歌浏览......
  • 背包问题集合
    dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。那么可以有两个方向推出来dp[i][j],不放物品i:由dp[i-1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i-1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进......
  • 高精度加法C++
    #include<iostream>#include<vector>usingnamespacestd;vector<int>Add(vector<int>&A,vector<int>&B){vector<int>C;intt=0;for(inti=0;i<A.size()||i<B.size();i++){if(i<A.size(......
  • 2023-04-10 网络流和最大流问题
    网络流和最大流问题1网络流和最大流问题阐述网络流基本概念网络流图中,从源点出发,在满足每条边容量限制的条件下,汇点t最多能接收多少流量s:sourcet:target网络流需要满足的限制容量限制平衡限制:除了源点s和汇点t,对于每一个点,流入量等于流出量从源点s流出的流量,一定......
  • 百钱百鸡问题
      #include<iostream>usingnamespacestd;intmain(){ intcock,hen,chicken; floata=5,b=3,c=1.0/3; for(cock=0;cock<20;cock++) { for(hen=0;hen<33;hen++) { chicken=100-cock-hen; if(a*cock+b*hen+c*......
  • 百钱百鸡问题
    一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱,现在要用百钱买百鸡,请问公鸡、母鸡、小鸡各多少只?因为一只公鸡五钱,一只母鸡三钱,一只小鸡三分之一钱,公鸡、母鸡、小鸡一共100只,买鸡共消费100钱,先定义公鸡、母鸡、小鸡的数量a,b,c,则a+b+c=100,5*a+3*b+c/3=100;公鸡最多为20只,母鸡最多为33......
  • js 数据转换问题
    题目将下面的数据结构[{"id":"1","pid":"","title":"标题1"},{"id":"2","pid":"1","title&qu......
  • 百鸡问题以及借书方案知多少
    百钱百鸡问题一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱,现在要用百钱买百鸡,请问公鸡,母鸡,小鸡各多少只根据数学知识可以转化为方程组: 解题思路:根据鸡的数量不超过100只以及总价格不超过100,可以得出:公鸡数量为0-20,母鸡数量为0-33,小鸡数量为0-100。运用for循环嵌套实现公鸡,母......
  • 解决win11不能复制粘贴的问题
    系统版本:windows1121H2搜狗输入法版本:13.3.0.6977原问题答案:https://answers.microsoft.com/zh-hans/windows/forum/all/win11%E7%9A%84ctrl%E5%BF%AB%E6%8D%B7%E9%94%AE/23f99ac5-ec3a-463f-a722-02d157b4c9a0在win11的21H2版本中,如果安装了搜狗输入法就有可能出现......
  • Maven 资源导出问题
    <!--在build中配置resources,来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/resources</directory><excludes><exclude>*......