如何正确对pandas DataFrame的两列float数值做减法避免精度损失
问题原因
- 列名拼写错误:你定义的DataFrame列名是全大写的
OPEN、CLOSE,但代码里用的是"Close"、"Open",大小写不匹配会读取不到正确值。 - 循环边界错误:
dt.size返回的是DataFrame总元素个数(你示例的dt是12行2列,size为24),直接循环到dt.size-1会出现行索引越界。 Decimal精度设置不生效的核心原因:getcontext().prec控制的是Decimal运算过程的有效数字位数,不会限制从float转换Decimal时的精度。float本身是二进制存储的,很多十进制小数没法精确表示,你直接把float丢给Decimal构造函数,会把float底层的二进制近似值完整转过来,自然会出现很长的小数位。
解决方案
方案1:保留Decimal方案(适合对精度要求极高的场景)
核心是不要直接从float转Decimal,先把数值格式化为对应精度的字符串再转换,就能避开float的二进制误差:
import pandas as pd import numpy as np from decimal import Decimal, getcontext # 控制运算精度为6位有效数字 getcontext().prec = 6 dt = pd.DataFrame({"OPEN": [-0.00011,-0.0114, 0.0066,-0.0044,-0.0012,-0.0005, 0.0005,-0.0037, -0.0029, 0.0034, 0.0003, 0.0001 ], "CLOSE": [-1.20011,-3.0114, 0.4066,-0.0074,-0.0016,-5.0005, 0.0225,-0.0027, -0.0026, 0.0064, 0.0043, 4.0001 ],}) delta = [] for i in range(len(dt)): # 先转成5位小数的字符串再转Decimal,避开float原生精度误差 open_val = Decimal(f"{dt.loc[i,'OPEN']:.5f}") close_val = Decimal(f"{dt.loc[i,'CLOSE']:.5f}") delta_val = open_val - close_val delta.append(float(delta_val)) # 也可以根据需求直接存Decimal类型 dt["delta"] = delta
方案2:更简单的pandas原生方案(适合4-5位精度的常规场景)
你需要的精度只有5位,直接做减法后保留5位小数即可,完全能覆盖需求,代码更简洁、性能也更好:
dt["delta"] = (dt["OPEN"] - dt["CLOSE"]).round(5)
该方案完全匹配你提到的0.0003-0.0002得到0.0001的输出要求。
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

