You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何最高效计算这类特殊加权求和问题

特殊求和值计算性能优化需求

我需要计算一类特殊求和值,目前尝试的实现策略效率不够理想,希望能获得更优的实现方案。


预计算部分

这部分逻辑固定不变,N可调整,定义Uf的f函数也可调整,所有项均预先完成计算:

import time

N = 10000

Uf = ([0]*2) + [1/f for f in range(2,N+1)]

频率数据处理部分

实际业务中fs的格式不同,但本质一致:包含多个f值,每个值重复指定次数,例如示例中f=2重复1000次,f=9998重复2次等。我将每个f值的出现频率存入列表Ff,采用列表存储是为了可以直接通过Ff[f]快速获取对应频率,其余位置填充0是因为后续计算中大量f值的频率会频繁增减,预先填充数值可大幅简化操作:

fs = [[2]*1000, [9998]*2, [5]*2000, [9995]*1, [10]*585, [20]*878,
      [50]*2580, [77]*1487, [1100]*5454, [2300]*4047, [3700]*5471]

Ff = [0]*(N+1)

for l in fs:
    Ff[l[0]] = len(l)

初始求和实现

需要计算的求和值S如下:

S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N)])
print(S)
# 1085.5709951104413
%timeit S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N)])
# 3.93 ms ± 327 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

优化尝试1:遍历中过滤0值项

最初认为性能偏慢是因为累加了大量0值,因此添加了判断条件筛选有效项:

S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N) if (Ff[f] + Ff[N-f] > 0)])
print(S)
# 1085.5709951104413
%timeit S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N) if (Ff[f] + Ff[N-f] > 0)])
# 2.53 ms ± 120 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

该方案有一定优化,但提升幅度不大。改用逻辑或条件判断有效项反而导致性能略降:

S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N) if ((Ff[f] > 0) | (Ff[N-f] > 0))])
print(S)
# 1085.5709951104413
%timeit S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in range(2,N) if ((Ff[f] > 0) | (Ff[N-f] > 0))])
# 3.02 ms ± 175 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

优化尝试2:预筛选有效f项

测试发现预先筛选出所有有效f项后再求和,性能提升非常明显:

f_on = [f for f,_ in enumerate(Ff) if ((Ff[f] > 0) | (Ff[N-f] > 0))]
S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in f_on])
print(S)
# 1085.5709951104413
%timeit S = sum([(Ff[f]+Ff[N-f])*Uf[f] for f in f_on])
# 6.12 µs ± 327 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

优化尝试3:改用字典存储频率

之后尝试放弃列表Ff改用字典存储频率,利用字典的键自动标识有效f值。为避免键不存在报错,封装了取值函数,同时需要将字典键和对应N-f的所有值去重后作为求和遍历范围:

# 字典方法
Fr_dict = dict()
for l in fs:
    Fr_dict[l[0]] = len(l)

def Fr(f):
    if f in Fr_dict:
        Fr = Fr_dict[f]
    else:
        Fr = 0
    return Fr

S = sum([(Fr(f)+Fr(N-f))*Uf[f] for f in set(list(Fr_dict.keys())+[N-f for f in Fr_dict.keys()])])
print(S)
# 1085.570995110441
%timeit S = sum([(Fr(f)+Fr(N-f))*Uf[f] for f in set(list(Fr_dict.keys())+[N-f for f in Fr_dict.keys()])])
# 16.3 µs ± 452 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

待优化问题

目前的实现基本满足需求,但担心N变大后性能会出现瓶颈。是否存在其他更优的实现方案,或者对现有方法的优化思路,可以进一步提升计算效率?


内容的提问来源于stack exchange,提问作者user6376297

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:15:03