如何在Numpy数组中高效低内存存储指定浮点数?
最优存储方案对比:日期时分浮点数的Numpy低内存存储
问题根源
你遇到的half(float16)和single(float32)失真问题,本质是精度不足:
- float16仅能精确表示0~1024范围内的整数,19576远超这个范围,必然出现失真;
- float32的小数部分有效位数仅6~7位,19576.4125的二进制无法被float32精确存储,导致舍入误差。
三种方案对比
1. 转换为整数存储(乘以10000)
这是最优方案,兼顾内存效率和精度:
- 内存占用:将
19576.4125乘以10000得到195764125,用int32类型存储即可(int32最大值为2147483647,完全覆盖该数值),每个元素仅4字节,比float64省一半内存,和float32内存占用相同但精度无损。 - 操作便利性:读取时只需除以10000,Numpy支持向量运算,性能无损耗:
import numpy as np # 存储时转换 ts_int = int(round(get_timestamp() * 10000)) arr = np.array([ts_int], dtype=np.int32) # 读取时还原 ts_float = arr[0] / 10000 - 优势:内存高效、精度完全保留、计算成本低。
2. 使用float64存储
- 内存占用:每个元素8字节,内存开销是int32的两倍,不适合大规模数据集。
- 操作便利性:无需转换,直接存储和使用,代码最简单。
- 适用场景:数据量小、对内存要求不高时可以选用,但并非最优选择。
3. 字符串存储
完全不推荐,理由如下:
- 内存占用:每个字符串至少占用9字节(比如"19576.4125"),远高于数值类型,内存效率极低。
- 操作便利性:无法直接进行数值计算,必须先转换回数值类型,性能损耗大且代码繁琐。
额外优化:修正原时间戳生成函数
你的get_timestamp函数存在一个小bug:now.replace(microsecond=0, second=0)没有重新赋值给now,导致实际计算时仍会包含秒和微秒的影响。修正后的函数:
from datetime import datetime def get_timestamp() -> float: now = datetime.now() # replace方法返回新对象,必须重新赋值 now = now.replace(microsecond=0, second=0) _1970 = datetime(1970, 1, 1, 0, 0, 0) td = now - _1970 days = td.days hours, remainder = divmod(td.seconds, 3600) minutes, _ = divmod(remainder, 60) timestamp = days + hours / 24 + minutes / 1440 return round(timestamp, 4)
内容的提问来源于stack exchange,提问作者DazzRick
相关产品推荐
相关产品推荐

