Python中的阶乘函数


Answers:


191

最简单的方法是使用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

递归方法:

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

请注意,阶乘函数仅针对正整数定义,因此您还应该检查n >= 0and that isinstance(n, int)。如果不是,分别提高a ValueError或a TypeErrormath.factorial会为您解决这个问题。


2
我不了解如何factorialfactorial函数中使用。您如何在当前定义的函数中使用相同的函数?我是Python的新手,所以我只是想了解。
2014年

8
@ J82:这里使用的概念称为递归(en.wikipedia.org/wiki/Recursion_(computer_science))-调用自身的函数非常好,并且经常有用。
schnaader 2014年

除非您增加Python的递归限制,否则递归函数将为RecursionError大于998的任何数字引发a (尝试factorial(999)
Boris

114

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

import math
math.factorial(n)

从Python 3.9开始,将传递float给此函数将引发DeprecationWarning。如果要执行此操作,则需要转换nint显式:math.factorial(int(n)),该参数将舍弃小数点后的所有内容,因此您可能需要检查一下n.is_integer()
Boris

25

确实没有必要,因为这是一个很旧的线程。但是我在这里做的另一种方法是使用while循环来计算整数的阶乘。

def factorial(n):
    num = 1
    while n >= 1:
        num = num * n
        n = n - 1
    return num

4
factorial(-1)将返回1,应引发ValueError或其他错误。
f.rodrigues

如果您使用小数点后的数字传递浮点数,则此函数将产生错误的结果。
鲍里斯(Boris)

使用此功能,我想打印出前四个整数的阶乘。当我与交换num = num * n行位置 n = n - 1并对其运行时,for i in range(1, 5): print('Factorial of', i, 'is', factorial(i))对于每个阶乘,输出为0。我想知道为什么num = num * n需要首先出现的理由。谢谢!!

18

现有解决方案

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

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)


5

如果您使用的是Python2.5或更旧版本,请尝试

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

对于较新的Python,如此处其他答案所示,数学模块中有阶乘


这是仅限Python 2的答案,reduce已从Python 3中删除
Boris

@Boris,在Python3你只需要添加from functools import reduce
约翰·拉ROOY

它被删除是有原因的,您不应该使用它artima.com/weblogs/viewpost.jsp?thread=98196
Boris,

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

4

使用for-loop,从开始倒数n

def factorial(n):
    base = 1
    for i in range(n, 0, -1):
        base = base * i
    print(base)

3

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

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

或使用内置函数数学

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

检查运行结果

cProfile.run('fact(126000)')

5 function calls in 0.272 seconds

1
我认为while循环看起来更干净<!-语言:python-> def fact(n):ret = 1而n> 1:n,ret = n-1,ret * n return ret
edilio

1
def factorial(n):
    result = 1
    i = n * (n -1)
    while n >= 1:
        result = result * n
        n = n - 1
    return result

print (factorial(10)) #prints 3628800

1

这是我的尝试

>>> import math
>>> def factorial_verbose(number):
...     for i in range(number):
...             yield f'{i + 1} x '
...
>>> res = ''.join([x for x in factorial_verbose(5)])
>>> res = ' '.join([res[:len(res)-3], '=', str(math.factorial(5))])
>>> res
'1 x 2 x 3 x 4 x 5 = 120'

@Nir Levy,一件有趣的小事
Pedro Rodrigues

1

一条线,快速且大量也可以:

#use python3.6.x for f-string
fact = lambda x: globals()["x"] if exec(f'x=1\nfor i in range(1, {x+1}):\n\tx*=i', globals()) is None else None

0

我知道已经解决了这个问题,但这是具有反向范围列表理解的另一种方法,使范围更易于阅读和更紧凑:

    #   1. Ensure input number is an integer by attempting to cast value to int
    #       1a. To accomplish, we attempt to cast the input value to int() type and catch the TypeError/ValueError 
    #           if the conversion cannot happen because the value type is incorrect
    #   2. Create a list of all numbers from n to 1 to then be multiplied against each other 
    #       using list comprehension and range loop in reverse order from highest number to smallest.
    #   3. Use reduce to walk the list of integers and multiply each against the next.
    #       3a. Here, reduce will call the registered lambda function for each element in the list.
    #           Reduce will execute lambda for the first 2 elements in the list, then the product is
    #           multiplied by the next element in the list, and so-on, until the list ends.

    try :
        num = int( num )
        return reduce( lambda x, y: x * y, [n for n in range(num, 0, -1)] )

    except ( TypeError, ValueError ) :
        raise InvalidInputException ( "Input must be an integer, greater than 0!" )

您可以在此要点中查看完整版本的代码:https : //gist.github.com/sadmicrowave/d4fbefc124eb69027d7a3131526e8c06


1
无需使用[n for n in range(num, 0, -1)]range已经可以迭代了。
Mark Mishyn

0

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

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

0

由n!表示的正整数n的阶乘是所有小于或等于n的正整数的乘积。

配方n! = n * (n-1) * (n-2) * (n-3) * (n-4) * ....... * 1

有几种方法可以通过使用内置函数/库等在python中找到阶乘。在这里,我参考了阶乘的基本定义创建了用户定义的函数。

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

print(factorial(4))

我们还可以使用recursive如下所示的技术来实现阶乘函数。但是此方法仅对较小的整数有效。因为在递归中,该函数被反复调用并需要一个内存空间来维护堆栈,所以对于大整数值查找阶乘而言,这不是一种有效或优化的方法。

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

print(factorial(4))


0

在下面的代码中,我输入要计算其阶乘的数字,此后,我将要计算其阶乘的->数字与从1,2,....(我想计算-1)

    f = int(input("Enter a number whose factorial you want to calculate = "))#Number 
                                           #whose factorial I want to calculate                              
for i in range(1,f): #assume I have taken f as 5
    f=f*i # In 1st iteration f=5*1 => 5 , in second iteration f = 5*2 => 10, 3rd 
          #iteration f = 10*3 =>30, 4th iteration f = 30*4 =>120  
print(f) #It will print the updated value of "f" i.e 120
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.