热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python:float64与float32转换、压缩比较与转换偏差

python原生类型中只有float,并没有float64和float32,但是

python原生类型中只有float,并没有float64和float32,但是在numpy中是有float64和32区分的。因此,互转是需要在特定的库下面进行,比如,numpy和dataframe之类。

结论:
1、互转的类型中,DataFrame和np.array是比较方便互转的。
2、大小差了一倍;
3、压缩时间也差了一倍(有时会到2倍);
4、转换偏差存在,看情况而异;

一、转换与压缩

import pickle
import sys
import pandas as pd
import random
import gzip
import time as t
import numpy as np
df = pd.DataFrame([123456789.0])
df = df.astype('float32')
n =10000
_dict_f64 = {"open": [random.random() +10.0 for i in range(n)] ,
"high":[random.random() +10.0 for i in range(n)] ,
"low":[random.random() +10.0 for i in range(n)] ,
"close":[random.random() +10.0 for i in range(n)] ,
}
# np.array,list的情况
open_f32 = np.array(_dict_f64["open"]).astype('float32')
open_f64_list = _dict_f64["open"]
open_f64_np = np.array(open_f64_list)
print("np.array[32和64] 与 f64_list比较: ")
print(f"open_f64_list size : {sys.getsizeof(open_f64_list)}")
print(f"open_f64_np size : {sys.getsizeof(open_f64_np)}")
print(f"open_f32_np size : {sys.getsizeof(open_f32)}")
# list 不能直接转,np.array可以f64转f32
print("df_64和df_32转换与大小比较:")
df_f64 = pd.DataFrame(_dict_f64)
print(f"df_f64 size : {sys.getsizeof(df_f64)}")
df_f32 = df_f64.astype('float32')
print(f"df_f32 size : {sys.getsizeof(df_f32)}")
print(f"f64和f32类型pickle二进制文件大小比较:")
pk_f64 = pickle.dumps(df_f64)
pk_dict = pickle.dumps(_dict_f64)
pk_f32 = pickle.dumps(df_f32)
print(f"pk_f64 size : {sys.getsizeof(pk_f64)}")
print(f"pk_f32 size : {sys.getsizeof(pk_f32)}")
print(f"pk_f64_dict size : {sys.getsizeof(pk_dict)}")
## 可以看一下差异
print("f64和f32类型二进制pickle文件压缩时间开销比较:")
t0 = t.time()
gzip_f64 = gzip.compress(pk_f64)
print(f"pk_64 -> compress cost time : {t.time() -t0} seconds!")
t1 = t.time()
gzip_f32 = gzip.compress(pk_f32)
print(f"pk_32 -> compress cost time : {t.time() -t1} seconds!")

输出:

np.array[32和64] 与 f64_list比较:
open_f64_list size : 87616
open_f64_np size : 80112
open_f32_np size : 40112
df_64和df_32转换与大小比较:
df_f64 size : 320144
df_f32 size : 160144
f64和f32类型pickle二进制文件大小比较:
pk_f64 size : 320725
pk_f32 size : 160725
pk_f64_dict size : 360210
f64和f32类型二进制pickle文件压缩时间开销比较:
pk_64 -> compress cost time : 0.02867913246154785 seconds!
pk_32 -> compress cost time : 0.009557962417602539 seconds!

二、floa64和np.float64

1、float64 list 与np.float64 array

a = np.array([1.0,2.0])
b = np.array([np.float64(1.0),np.float64(2.0)])
c = [1.0,2.0]
print(f" a: {sys.getsizeof(a)}")
print(f" b: {sys.getsizeof(b)}")
print(f" c: {sys.getsizeof(c)}")

输出:
a: 128
b: 128
c: 72
可见,np.float64要比单个原生的占用字节要大。

2、dict类型中比较


n =100000
k = 50000.0
_dict_f64_primitive = {"open": [random.random() +k for i in range(n)] ,
"high":[random.random() +k for i in range(n)] ,
"low":[random.random() +k for i in range(n)] ,
"close":[random.random() +k for i in range(n)] ,
}
_dict_f64_np = {"open": np.array(_dict_f64_primitive["open"]) ,
"high":np.array(_dict_f64_primitive["high"]) ,
"low":np.array(_dict_f64_primitive["low"]) ,
"close":np.array(_dict_f64_primitive["close"]) ,
}
_dict_f64_np2 = {"open": np.array([random.random() +k for i in range(n)] ) ,
"high":np.array([random.random() +k for i in range(n)] ) ,
"low":np.array([random.random() +k for i in range(n)] ) ,
"close":np.array([random.random() +k for i in range(n)] ) ,
}
print(f"_dict_f64_primitive size : {sys.getsizeof(_dict_f64_primitive)}")
print(f"_dict_f64_np size : {sys.getsizeof(_dict_f64_np)}")
print(f"_dict_f64_np2 size : {sys.getsizeof(_dict_f64_np2)}\n")
t0 = t.time()
pk_primitive = pickle.dumps(_dict_f64_primitive)
t1 = t.time()
pk_np = pickle.dumps(_dict_f64_np)
t2 = t.time()
pk_np2 = pickle.dumps(_dict_f64_np2)
t3 = t.time()
gzip_primitive = gzip.compress(pk_primitive)
t4 =t.time()
gzip_np = gzip.compress(pk_np)
t5 =t.time()
gzip_np2 = gzip.compress(pk_np2)
t6 =t.time()
print(f"pk_primitive -> binary cost time :{t1-t0} seconds")
print(f"pk_np -> binary cost time :{t2-t1} seconds")
print(f"pk_np2 -> binary cost time :{t3-t2} seconds\n")
print(f"pk_primitive -> cpmpress cost time :{t4-t3} seconds")
print(f"pk_np -> compress cost time :{t5-t4} seconds")
print(f"pk_np2 -> compress cost time :{t6-t5} seconds")

输出:

_dict_f64_primitive size : 232
_dict_f64_np size : 232
_dict_f64_np2 size : 232
pk_primitive -> binary cost time :0.012560844421386719 seconds
pk_np -> binary cost time :0.006933927536010742 seconds
pk_np2 -> binary cost time :0.0059435367584228516 seconds
pk_primitive -> cpmpress cost time :3.5468034744262695 seconds
pk_np -> compress cost time :2.197758674621582 seconds
pk_np2 -> compress cost time :2.230668783187866 seconds

但这三者占用空间又相同。但序列化和压缩用时有一定差异。感觉numpy要快一些。

三、转换的偏差

numbers = [12.345888888888888888888,123456789.0,123456789.978654412,123456782229.978,3309.07,7896.353,123456789.88]
for number in numbers:
assert isinstance(number,float)
f_64 = np.float64(number)
f_32 = np.float32(number)
f_32_64 = np.float64(f_32)

error = f_64 - f_32_64
print(f"f_64 : {type(f_64)} value :{f_64} ")
print(f"f_32 : {type(f_32)} value :{f_32} error : {error}" )
print(f"f_32_64 : {type(f_32_64)} value :{f_32} \n" )

输出:

f_64 : value :12.345888888888888
f_32 : value :12.3458890914917 error : -2.0260281097250754e-07
f_32_64 : value :12.3458890914917
f_64 : value :123456789.0
f_32 : value :123456792.0 error : -3.0
f_32_64 : value :123456792.0
f_64 : value :123456789.97865441
f_32 : value :123456792.0 error : -2.0213455855846405
f_32_64 : value :123456792.0
f_64 : value :123456782229.978
f_32 : value :123456782336.0 error : -106.02200317382812
f_32_64 : value :123456782336.0
f_64 : value :3309.07
f_32 : value :3309.070068359375 error : -6.835937483629095e-05
f_32_64 : value :3309.070068359375
f_64 : value :7896.353
f_32 : value :7896.35302734375 error : -2.734374993451638e-05
f_32_64 : value :7896.35302734375
f_64 : value :123456789.88
f_32 : value :123456792.0 error : -2.1200000047683716
f_32_64 : value :123456792.0

比如:123456789.0 【f64】 ->【f32】这么简单转换却存在难以理解的偏差:

f_32 : value :123456792.0 error : -3.0
f_32_64 : value :123456792.0

那么问题是:如何减少这种转换带来的偏差?目测了一下,如果数值在1000万以下的float,转换的误差总体上是0.-0.1之间。但这个不太成为数据库的考虑项。数据库层次还是需要保真,否则失去就是依赖;具体应用层次,那仁者见仁。


推荐阅读
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • MPLS VP恩 后门链路shamlink实验及配置步骤
    本文介绍了MPLS VP恩 后门链路shamlink的实验步骤及配置过程,包括拓扑、CE1、PE1、P1、P2、PE2和CE2的配置。详细讲解了shamlink实验的目的和操作步骤,帮助读者理解和实践该技术。 ... [详细]
  • 本文介绍了在Python中使用zlib模块进行字符串的压缩与解压缩的方法,并探讨了其在内存优化方面的应用。通过压缩存储URL等长字符串,可以大大降低内存消耗,虽然处理时间会增加,但是整体效果显著。同时,给出了参考链接,供进一步学习和应用。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
author-avatar
woooooso_776
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有