Python计算CSV发电量总和出现精度误差及优化方案咨询
误差来源
这个误差是二进制浮点数运算的固有精度问题:绝大多数十进制有限小数(比如0.1、0.2等)无法用64位双精度浮点数(也就是Python里的float类型)精确表示,存储时会做近似截断,多次累加后截断误差会逐步累积,最终就会出现这种和理论值差了极小尾数的情况,属于浮点数运算的正常现象,和你的计算逻辑、CSV读取逻辑无关。
更优实现方案
有几个可以优化的点:
- 去掉多余的格式转换步骤:Python内置的
csv模块本身支持自定义分隔符,不需要提前用tr命令把分号转成逗号,直接读取原CSV文件即可,减少不必要的IO操作和文件冗余。 - 解决浮点精度误差:如果对数值精度要求高,可以用Python标准库的
decimal模块做精确的十进制运算,从根源上避免浮点累加误差;如果只需要正常显示结果,也可以在输出时按需求保留小数位数即可。 - 可选实现第一种计算逻辑:如果CSV的首尾行第二个字段的差值就是发电总量,这种方案的计算效率远高于逐行累加,尤其是大文件场景下优势更明显。
优化后的累加方案代码(无需提前转格式、无精度误差)
import csv from decimal import Decimal total = Decimal(0) # 直接读取原分号分隔的CSV文件 with open('/home/LoadLive/day.csv', 'r', encoding='utf-8') as f: reader = csv.reader(f, delimiter=';') for row in reader: total += Decimal(row[2]) # 按需求输出,转float也不会有多余误差 print(f'The total is {float(total)}') # 若需要输出精确十进制值:print(f'The total is {total}')
第一种计算逻辑的实现代码(效率更高)
import csv from decimal import Decimal with open('/home/LoadLive/day.csv', 'r', encoding='utf-8') as f: reader = csv.reader(f, delimiter=';') # 读取首行第二个字段值 first_val = Decimal(next(reader)[1]) # 遍历到最后一行 last_row = None for row in reader: last_row = row last_val = Decimal(last_row[1]) total = last_val - first_val print(f'The total is {float(total)}')
如果不需要高精度运算,只是不想显示多余的尾数,也可以直接格式化输出即可:
# 仅修改原来代码的输出行即可 print('The total is {:.2f}'.format(total))
内容的提问来源于stack exchange,提问作者Geertz
相关产品推荐
相关产品推荐

