如何用Numpy高效计算按规则分配的客户订单平均价格及浮点精度处理
高效Numpy实现方案
核心思路
通过累积和区间匹配替代生成大数组,直接计算每个客户从不同价格库存中分配到的数量,彻底避免内存浪费。
代码实现
import numpy as np orders = np.array([21, 6, 3], dtype=np.int64) quantity = np.array([16, 14], dtype=np.int64) price = np.array([30.5, 35.5], dtype=np.double) # 1. 计算订单和库存的累积量(用于划分区间) order_cumsum = np.concatenate([[0], orders.cumsum()]) # 结果:[0, 21, 27, 30] stock_cumsum = np.concatenate([[0], quantity.cumsum()]) # 结果:[0, 16, 30] # 2. 计算每个订单区间与库存区间的重叠数量 start = order_cumsum[:-1, np.newaxis] end = order_cumsum[1:, np.newaxis] stock_start = stock_cumsum[:-1] stock_end = stock_cumsum[1:] # 取区间交集的有效长度,无重叠则为0 overlap = np.maximum(0, np.minimum(end, stock_end) - np.maximum(start, stock_start)) # 3. 计算每个客户的总采购金额与平均价格 total_cost = (overlap * price).sum(axis=1) mean_prices = total_cost / orders # 输出结果 people = ['mark', 'greg', 'paul'] for name, mp, qty in zip(people, mean_prices, orders): print(f"{name}: 平均价格 {mp:.2f} 美元,采购量 {qty} 件")
结果解释
- Mark的21件:先分配16件30.5美元的库存,剩余5件从35.5美元库存中获取,平均价≈31.69美元
- Greg的6件:全部来自35.5美元库存,平均价=35.5美元
- Paul的3件:全部来自35.5美元库存,平均价=35.5美元
浮点精度问题解决
要确保mean_prices × 客户采购量 = 该客户总采购金额始终成立,需规避浮点运算的累积误差,可采用以下两种方案:
方案1:整数化金额计算(推荐)
将价格转换为最小货币单位(如美分),用整数完成所有计算,最后再转回美元,从根源避免浮点误差:
# 转换为美分(整数类型) price_cents = (price * 100).astype(np.int64) total_cost_cents = (overlap * price_cents).sum(axis=1) mean_prices = total_cost_cents / (orders * 100) # 转回美元 # 验证等式(完全相等) assert np.all(mean_prices * orders * 100 == total_cost_cents)
方案2:使用高精度浮点类型
如果平台支持,用np.float128替代np.double,大幅降低浮点运算误差:
price_high_prec = price.astype(np.float128) total_cost = (overlap * price_high_prec).sum(axis=1) mean_prices = total_cost / orders # 验证等式(近似相等) assert np.allclose(mean_prices * orders, total_cost)
关键注意事项
- 优先用总金额 ÷ 采购量的方式计算平均价,避免拆分价格段后再加权平均的冗余运算
- 浮点场景下用
np.allclose判断近似相等,整数场景直接用==验证完全相等
内容的提问来源于stack exchange,提问作者barrelquentin997
相关产品推荐
相关产品推荐

