我在搞乱 lambda 函数,我明白我可以用简单的方式用它做什么,但是当我尝试更高级的东西时,我遇到了错误,我不明白为什么。
如果您能告诉我哪里出错了,这就是我正在尝试的方法。
import math
C = lambda n,k: math.factorial(n)/(math.factorial(k))(math.factorial(n-k))
print C(10,5)
我应该注意到我在尝试在键盘上运行代码时遇到了错误。我无权访问 Idle。
试试这个:
from math import factorial
from __future__ import division
C = lambda n, k : factorial(n) / factorial(k) * factorial(n-k)
print C(10,5)
> 3628800.0
您缺少 a *
,并且除法可能应该考虑小数,因此旧的除法运算符/
不会这样做。这就是为什么我要导入/
执行小数除法的新运算符。
更新:
好吧,毕竟这似乎是 Codepad 的错——它支持Python 2.5.1,并且factorial
是在 Python 2.6 中添加的。只需实现您自己的阶乘函数并完成它,或者更好地开始使用真正的 Python 解释器。
def factorial(n):
fac = 1
for i in xrange(1, n+1):
fac *= i
return fac
我认为您在*
第二个 2 阶乘子句之间缺少 a 。你得到一个错误是因为你试图运行(math.factorial(k))(math.factorial(n-k))
,它变成了类似的东西10(math.factorial(n-k)
,这是没有意义的。
大概您希望计算的值是“n-choose-k”,即一次取 k 的 n 个事物的组合数。公式是n!/(k! * (n-k)!)
。当缺失*
值添加到您的计算中时,它会产生n!/k! * (n-k)!
,它等于(n!/k!)*(n-k)!
。(注意,k!
均分n!
。)例如,当 n=10 和 k=5 时,C(10,5) 应为 3628800/(120*120) = 252,但您的计算结果为 3628800/120*120 = 3628800,这是不正确的 14400 倍。
您当然可以修复括号:
>>> C = lambda n,k: math.factorial(n)/(math.factorial(k)*math.factorial(n-k))
>>> C(10,5)
252
但请注意,如果 math.factorial(j) 需要 j-1 次乘法来计算,则 C(n,k) 需要 n-1+k-1+nk-1+1 = 2*n-2 次乘法和一次除法。这大约是所需乘法运算次数的四倍。下面显示的代码使用 j 乘和 j 除,其中 j 是 k 和 nk 中的较小者,因此 j 最多为 n/2。在某些机器上,除法比乘法慢得多,但在大多数机器上,j 次乘法和 j 次除法的运行速度要比 2*n-2 次乘法和一次除法快得多。
更重要的是,C(n,k) 远小于 n!。每当 n 超过 20 时,通过n!/(k!*(n-k)!)
公式计算需要超过 64 位的精度。例如,C(21,1) 返回值 21L。相比之下,在需要超过 64 位来计算 D(62,31)=465428353255261088L 之前,下面的代码最多计算 D(61,30)=232714176627630544。(我将函数命名为“D”而不是“C”以避免名称冲突。)
对于大型快速机器上的小型计算,额外的乘法和额外的精度要求并不重要。然而,对于小型机器上的大型计算,它们变得很重要。
简而言之,D() 中的乘法和除法的顺序保持了看起来最小的最大中间值。最大值出现在 for 循环的最后一遍。另请注意,在 for 循环中,i 始终是 c*j 的精确除数,并且不会发生截断。这是计算“n-choose-k”的相当标准的算法。
def D(n, k):
c, j, k = 1, n, min(k,n-k)
for i in range(1,k+1):
c, j = c*j/i, j-1
return c
口译员的结果:
>>> D(10,5)
252
>>> D(61,30)
232714176627630544
>>> D(62,31)
465428353255261088L