在从元组向量(残差,模数)计算中国剩余定理时,以下代码失败:
c = ((1,5),(3,7),(11,13),(19,23))
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
complements = (N/ni for ni in moduli)
scaled_residues = (product(pair) for pair in zip(residues,complements))
inverses = (modular_inverse(*pair) for pair in zip(complements,moduli))
si = (product(u) for u in zip(scaled_residues,inverses))
result = sum(si) % N
return result
将结果赋予 0 (我猜生成的迭代是空的)。然而,以下代码完美无缺:
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
complements = list((N/ni for ni in moduli)) # <-- listed
scaled_residues = (product(pair) for pair in zip(residues,complements))
inverses = (modular_inverse(*pair) for pair in zip(complements,moduli))
si = (product(u) for u in zip(scaled_residues,inverses))
result = sum(si) % N
return result
产生(a) 8851 的正确结果。
为什么我必须list(
第一台发电机之一?将list
添加到任何后续生成器不会更改fail(0)结果。仅列出第一个生成器会生成正确的结果。这是怎么回事?
答案 0 :(得分:6)
您在complements
上重复两次。您只能在生成器表达式上迭代一次。
如果您使用的是Python 2.x,则zip(residues,complements)
将使用complements
并且zip(complements,moduli)
没有任何内容。在Python 3.x上zip
是一个生成器本身,当sum()
实际运行生成器时,问题会出现在代码中。每次迭代都会从complements
中提取两个项目。
答案 1 :(得分:0)
根据答案中的建议作为参考,我重新实现了问题中的代码如下:
def complements(moduli,N):
return (N/ni for ni in moduli)
def scaled_residues(residues,complements):
return (product(pair) for pair in zip(residues,complements))
def inverses(complements,moduli):
return (modular_inverse(*pair) for pair in zip(complements,moduli))
def crt_residue_terms(scaled_residues,inverses):
return (product(u) for u in zip(scaled_residues,inverses))
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
return sum(
crt_residue_terms(
scaled_residues(residues,complements(moduli,N)),
inverses(complements(moduli,N),moduli)
)) % N
现在生成 8851 的正确结果,而不使用任何列表。凉。