【问题标题】:Unable to make a factorial function in Python无法在 Python 中创建阶乘函数
【发布时间】:2012-01-29 10:23:55
【问题描述】:

我的代码

import sys

number=int(sys.argv[1])

if number == 0
    fact=1
else
    fact=number
for (x=1; x<number; x++)
    fact*=x;             // mistake probably here

print fact

我得到了错误

File "factorial.py", line 5
    if number == 0
                 ^
SyntaxError: invalid syntax

如何在 Python 中创建阶乘函数?

【问题讨论】:

  • 虽然我确定您只是想学习 python,但请注意,这不是计算 n 的一种非常有效的方法!。
  • @WaffleMatt:lambda 演算方法是最好的方法吗?

标签: python factorial


【解决方案1】:

你的错误所在的行应该是

if number == 0:

注意末尾的冒号。

此外,您需要在 else 和 for 之后添加相同的冒号。冒号的工作方式与其他语言中的 {} 类似。

最后,这不是 Python 中 for 循环的工作方式。您要使用该列表的代码是

for x in range(1,number):

如果你把它放在 C 风格的语言中,它会产生与你所写内容相同的效果。

编辑:糟糕,我给出的 for 循环是错误的,它应该包含 0。我更新了代码以更正此问题。

【讨论】:

    【解决方案2】:

    我了解您可能出于教育原因尝试自己实现此功能。

    但是,如果没有,我建议使用math modules 内置阶乘函数(注意:需要 python 2.6 或更高版本):

    >>> import math
    >>> math.factorial(5)
    120
    

    这个模块是用 C 编写的,因此,它会比用 python 编写快得多。 (不过,如果您不计算大型阶乘,那么无论哪种方式都不会太慢)。

    【讨论】:

      【解决方案3】:

      这是您的代码,已修复并正常工作:

      import sys
      number = int(sys.argv[1])
      fact = 1
      for x in range(1, number+1):
          fact *= x
      
      print fact
      

      (对于不知道的人来说,阶乘为零是一,我必须查一下。8-)

      ifelsefor 等后面需要冒号,而for 在 Python 中的工作方式与 C 不同。

      【讨论】:

        【解决方案4】:

        Mark Rushakoff 的 fact(n) 函数如此高效的原因是他错过了 reduce() 函数。因此它实际上从未进行过计算。

        更正它的内容(我明白了):

        import operator, timeit, math
        #
        def fact1(n):  return reduce(lambda x,y: x*y,  range(1,n+1),1)
        def fact1x(n): return reduce(lambda x,y: x*y, xrange(1,n+1),1)
        def fact2(n):  return reduce(operator.mul   ,  range(1,n+1),1)
        def fact2x(n): return reduce(operator.mul   , xrange(1,n+1),1)
        #
        def factorialtimer():
            for myfunc in [ "fact1", "fact1x", "fact2", "fact2x" ]:
                mytimer = timeit.Timer(myfunc+"(1500)", "from __main__ import "+myfunc)
                print("{0:15} : {1:2.6f}".format(myfunc, mytimer.timeit(number=1000)))
        
            mytimer = timeit.Timer("factorial(1500)", "from math import factorial")
            print("{0:15} : {1:2.6f}".format("math.factorial", mytimer.timeit(number=1000)))
        

        1500!、1000x 的结果输出:

        fact1           : 3.537624
        fact1x          : 4.448408
        fact2           : 4.390820
        fact2x          : 4.333070
        math.factorial  : 4.091470
        

        是的,我已经检查过它们都产生相同的值! 我不明白为什么 lambda xrange 比 lambda 范围差这么多。嗯。 版本: PythonWin 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on win32。

        嗯...重新运行它我得到了一些更可信的东西

        fact1           : 7.771696
        fact1x          : 7.799568
        fact2           : 7.056820
        fact2x          : 7.247851
        math.factorial  : 6.875827
        

        在 Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01) [GCC 4.3.4 20090804 (release) 1] 上 cygwin:

        fact1           : 6.547000
        fact1x          : 6.411000
        fact2           : 6.068000
        fact2x          : 6.246000
        math.factorial  : 6.276000
        

        真的很吵,不是吗?

        【讨论】:

          【解决方案5】:

          这是一个函数阶乘,你几乎要求它:

          >>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
          ... 
          >>> fact(5)
          120
          

          它不适用于 fact(0),但您可以担心 fact 范围之外的问题 :)


          Masi 曾询问函数式风格是否比 Richie 的实现更高效。根据我的快速基准测试(令我惊讶的是!)是的,我的速度更快。但是我们可以做一些改变。

          首先,我们可以按照另一条评论中的建议将lambda x,y: x*y 替换为operator.mul。 Python 的 lambda 运算符带来了不小的开销。其次,我们可以用xrange 代替rangexrange 应该在线性空间中工作,根据需要返回数字,而 range 一次创建整个列表。 (请注意,您几乎可以肯定必须使用xrange 来处理过大的数字范围)

          所以新的定义变成了:

          >>> import operator
          >>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
          ... 
          >>> fact2(5)
          120
          

          令我惊讶的是,这实际上导致性能下降。以下是问答基准:

          >>> def fact(n): return (lambda x,y: x*y, range(1,n+1))
          ... 
          >>> t1 = Timer("fact(500)", "from __main__ import fact")
          >>> print t1.timeit(number = 500)
          0.00656795501709
          
          >>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
          ...
          >>> t2 = Timer("fact2(500)", "from __main__ import fact2")
          >>> print t2.timeit(number = 500)
          0.35856294632
          
          >>> def fact3(n): return reduce(operator.mul, range(1,n+1))
          ... 
          >>> t3 = Timer("fact3(500)", "from __main__ import fact3")
          >>> print t3.timeit(number = 500)
          0.354646205902
          
          >>> def fact4(n): return reduce(lambda x,y: x*y, xrange(1,n+1))
          ... 
          >>> t4 = Timer("fact4(500)", "from __main__ import fact4")
          >>> print t4.timeit(number = 500)
          0.479015111923
          
          >>> def fact5(n):
          ...     x = 1
          ...     for i in range(1, n+1):
          ...             x *= i
          ...     return x
          ... 
          >>> t5 = Timer("fact5(500)", "from __main__ import fact5")
          >>> print t5.timeit(number = 500)
          0.388549804688
          

          这是我的 Python 版本,以防有人想交叉检查我的结果:

          Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
          [GCC 4.3.3] on linux2
          

          【讨论】:

          • "lambda x,y: x*y" 可以拼写为 "operator.mul"(但显式优于隐式 8-)
          • @Mark:你的方法比 Richie 的代码更有效率吗? % 你能算出,例如,20000000!与您的代码完全一致?
          • @Mark:感谢您的编辑! --- 看来我们无法计算 20000000000!在孙的有生之年。
          • @Masi:使用简单算法进行 20000000 的阶乘不太可能很快。
          【解决方案6】:

          真的,最简单的选择是:

          def factorial(n):
              x = n
              for j in range(1, n):
                  x = j*x
              return x
          

          是的,不知何故,它起作用了。

          你怎么会没想到呢?我不知道。

          一个for 循环和一个乘法器,真的简单是最好的方法,对吧?

          编辑:哦,等等,我们正在为 CPU 效率最高的方式工作?呵呵……

          【讨论】:

            猜你喜欢
            • 2010-10-21
            • 1970-01-01
            • 2011-07-05
            • 2018-12-31
            • 2015-04-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多