使用np.trunc截断Pandas数据框小数位时出现异常舍入问题求助
解决Pandas浮点数截断三位小数的异常问题
出现这种异常是浮点数精度误差导致的:十进制小数(比如0.87、59.307)无法被二进制浮点数精确存储,实际存储值会有微小偏差——比如0.87可能存成0.8699999999999999,59.307存成59.306999999999996。当你执行np.trunc(df['QuantityReq']*1000)/1000时,这些偏差会被放大:0.8699999999999999×1000=869.9999999999999,np.trunc直接截断小数部分得到869,最终除以1000就是0.869,和预期不符。
解决方案
1. 用decimal模块精确处理(最可靠)
通过decimal模块直接以十进制逻辑运算,从根源避免二进制浮点数的精度损失:
from decimal import Decimal, ROUND_DOWN def truncate_to_three(x): # 先转字符串再初始化Decimal,避免浮点数转Decimal时的精度丢失 return Decimal(str(x)).quantize(Decimal('0.000'), rounding=ROUND_DOWN) df['Test'] = df['QuantityReq'].apply(truncate_to_three).astype(float)
2. 加极小偏移量修正(简便快速)
针对浮点数的微小负偏差,给原数值加一个极小的正数(比如1e-10),再执行截断操作:
import numpy as np df['Test'] = np.trunc((df['QuantityReq'] + 1e-10) * 1000) / 1000
注意:偏移量要足够小(不能超过0.0005),避免影响真正需要截断的小数部分。
3. 字符串格式化截断(适合简单场景)
通过字符串截取实现截断,注意处理整数和科学计数法的情况:
def truncate_str(x): # 处理科学计数法 if 'e' in str(x).lower(): x = float(f"{x:.10f}") parts = str(x).split('.') if len(parts) == 1: return float(f"{parts[0]}.000") else: # 截取前3位小数,不足补0 decimal_part = parts[1][:3].ljust(3, '0') return float(f"{parts[0]}.{decimal_part}") df['Test'] = df['QuantityReq'].apply(truncate_str)
内容的提问来源于stack exchange,提问作者Karthikeyan Manoharan
相关产品推荐
相关产品推荐

