【问题标题】:Function for factorial in PythonPython中的阶乘函数
【发布时间】:2011-07-05 10:04:48
【问题描述】:

如何在 Python 中计算整数的阶乘?

【问题讨论】:

    标签: python


    【解决方案1】:

    最简单的方法是使用math.factorial(Python 2.6 及以上版本可用):

    import math
    math.factorial(1000)
    

    如果您想/必须自己编写,可以使用迭代方法:

    def factorial(n):
        fact = 1
        for num in range(2, n + 1):
            fact *= num
        return fact
    

    recursive 方法:

    def factorial(n):
        if n < 2:
            return 1
        else:
            return n * factorial(n-1)
    

    请注意,factorial function 仅针对正整数定义,因此您还应该检查 n &gt;= 0isinstance(n, int)。如果不是,请分别提出ValueErrorTypeErrormath.factorial 会为您解决这个问题。

    【讨论】:

    • 我不明白如何在 factorial 函数中使用 factorial。如何在当前定义的函数中使用相同的函数?我是 Python 新手,所以我只是想了解一下。
    • @J82:这里使用的概念称为递归(en.wikipedia.org/wiki/Recursion_(computer_science))——一个调用自身的函数非常好,而且通常很有用。
    • 递归函数将为大于 998 的任何数字引发 RecursionError(尝试 factorial(999)),除非您 increase Python's recursion limit
    • 提高 CPython 的递归限制是危险的——你可以杀死解释器。如果可以提供帮助,只需 don't use recursion in Python(通常可以,如本例所示)。
    【解决方案2】:

    在 Python 2.6 及更高版本上,尝试:

    import math
    math.factorial(n)
    

    【讨论】:

    • Starting with Python 3.9,将float 传递给此函数将引发DeprecationWarning。如果您想这样做,您需要将n 显式转换为intmath.factorial(int(n)),这将丢弃小数点后的任何内容,因此您可能需要检查n.is_integer()
    【解决方案3】:
    def fact(n):
        f = 1
        for i in range(1, n + 1):
            f *= i
        return f
    

    【讨论】:

      【解决方案4】:

      如果您使用的是 Python 2.5 或更早版本,请尝试

      from operator import mul
      
      def factorial(n):
          return reduce(mul, range(1, n+1))
      

      对于较新版本的 Python,math 模块中有阶乘,如此处其他答案中给出的那样。

      【讨论】:

      • 这是一个仅限 Python 2 的答案,reduce 已从 Python 3 中删除。
      • @Boris,在 Python3 中你只需要添加from functools import reduce
      • 它被移除是有原因的,你不应该使用它artima.com/weblogs/viewpost.jsp?thread=98196
      【解决方案5】:

      现有解决方案

      最短且可能最快的解决方案是:

      from math import factorial
      print factorial(1000)
      

      构建你自己的

      您还可以构建自己的解决方案。通常你有两种方法。最适合我的是:

      from itertools import imap
      def factorial(x):
          return reduce(long.__mul__, imap(long, xrange(1, x + 1)))
      
      print factorial(1000)
      

      (它也适用于更大的数字,当结果变为long

      第二种实现方式是:

      def factorial(x):
          result = 1
          for i in xrange(2, x + 1):
              result *= i
          return result
      
      print factorial(1000)
      

      【讨论】:

      • operator.mul 可以用来代替long.__mul__,它可以在Python 2Python 3 中使用。
      【解决方案6】:
      def factorial(n):
          if n < 2:
              return 1
          return n * factorial(n - 1)
      

      【讨论】:

      【解决方案7】:

      出于性能原因,请不要使用递归。这将是灾难性的。

      def fact(n, total=1):
          while True:
              if n == 1:
                  return total
              n, total = n - 1, total * n
      

      查看运行结果

      cProfile.run('fact(126000)')
      

      4 function calls in 5.164 seconds
      

      使用堆栈很方便(就像递归调用一样),但它是有代价的:存储详细信息会占用大量内存。

      如果栈高,说明计算机存储了大量函数调用的信息。

      该方法只占用常量内存(如迭代)。

      或者使用'for'循环

      def fact(n):
          result = 1
          for i in range(2, n + 1):
              result *= i
          return result
      

      查看运行结果

      cProfile.run('fact(126000)')
      

      4 function calls in 4.708 seconds
      

      或者使用内置函数math

      def fact(n):
          return math.factorial(n)
      

      查看运行结果

      cProfile.run('fact(126000)')
      

      5 function calls in 0.272 seconds
      

      【讨论】:

      • 我觉得这个 while 循环看起来更干净了一点 def fact(n): ret = 1 while n > 1: n, ret = n - 1, ret * n 返回 ret
      • 看起来不错,大喊(大字体)递归是灾难性的,但你能支持一下吗?是的,你需要很多堆栈,但只需要很短的时间。昨天的“很多”就是今天的“一点点”,尤其是在计算方面。我们编写高级代码是为了不浪费我们的时间,而递归有助于做到这一点。今天,出于性能原因,您不需要太多低级代码
      【解决方案8】:

      另一种方法是使用np.prod,如下所示:

      def factorial(n):
          if n == 0:
              return 1
          else:
               return np.prod(np.arange(1,n+1))
      

      【讨论】:

        【解决方案9】:

        非递归解决方案,无导入:

        def factorial(x):
            return eval(' * '.join(map(str, range(1, x + 1))))
        

        【讨论】:

        • 将其与此处介绍的其他一些方法进行比较会很有趣。我的猜测是它的效率很低。
        【解决方案10】:

        如果你喜欢的话,你也可以递归地把它写成一行。这只是个人选择的问题。这里我们使用 Python 中的内联 if else,类似于 Java 中的 ternary operator

        Expression1 ? Expression2 : Expression3
        
        • 一行function call 方法:

          def factorial(n): return 1 if n == 0 else n * factorial(n-1)
          
        • 一行lambda函数做法:

          (虽然不建议将 lambda 函数直接分配给一个名称,因为这被认为是一种不好的做法,并且可能会给您的代码带来不一致。知道这一点总是好的。请参阅 PEP8 .)

          factorial = lambda n: 1 if n == 0 else n * factorial(n-1)
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-16
          • 1970-01-01
          • 1970-01-01
          • 2017-05-07
          • 2023-03-24
          • 1970-01-01
          • 2011-01-26
          • 2021-01-17
          相关资源
          最近更新 更多