2

我在搞乱 lambda 函数,我明白我可以用简单的方式用它做什么,但是当我尝试更高级的东西时,我遇到了错误,我不明白为什么。

如果您能告诉我哪里出错了,这就是我正在尝试的方法。

import math

C = lambda n,k: math.factorial(n)/(math.factorial(k))(math.factorial(n-k))

print C(10,5)

我应该注意到我在尝试在键盘上运行代码时遇到了错误。我无权访问 Idle。

4

3 回答 3

3

试试这个:

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
于 2012-10-28T01:16:28.263 回答
1

我认为您在*第二个 2 阶乘子句之间缺少 a 。你得到一个错误是因为你试图运行(math.factorial(k))(math.factorial(n-k)),它变成了类似的东西10(math.factorial(n-k),这是没有意义的。

于 2012-10-28T01:16:09.167 回答
1

大概您希望计算的值是“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
于 2012-10-28T06:16:48.733 回答