Función para Factorial en Python

135

¿Cómo hago para calcular un factorial de un entero en Python?

Nir Levy
fuente

Respuestas:

191

La forma más fácil es usar math.factorial(disponible en Python 2.6 y superior):

import math
math.factorial(1000)

Si quiere / tiene que escribirlo usted mismo, puede usar un enfoque iterativo:

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

o un enfoque recursivo :

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

Tenga en cuenta que la función factorial solo se define para enteros positivos, por lo que también debe verificar eso n >= 0y eso isinstance(n, int). Si no es así, elevar ValueErrorao a TypeErrorrespectivamente. math.factorialse encargará de esto por ti.

Schnaader
fuente
2
No entiendo cómo puedes usar factorialdentro de la factorialfunción. ¿Cómo puede usar la misma función dentro de la función que está definiendo actualmente? Soy nuevo en Python, así que solo estoy tratando de entender.
J82
8
@ J82: El concepto utilizado aquí se llama recursión ( en.wikipedia.org/wiki/Recursion_(computer_science) ): una función que se llama a sí misma es perfectamente adecuada y, a menudo, útil.
schnaader
La función recursiva elevará a RecursionErrorpara cualquier número mayor que 998 (intente factorial(999)) a menos que aumente el límite de
Boris
114

En Python 2.6 y superior, intente:

import math
math.factorial(n)
Joril
fuente
Comenzando con Python 3.9 , pasar a floata esta función generará a DeprecationWarning. Si desea hacer eso, debe convertirlo na un intexplícito: math.factorial(int(n))que descartará cualquier cosa después del decimal, por lo que es posible que desee verificar eson.is_integer()
Boris el
25

No es realmente necesario ya que este es un hilo tan antiguo. Pero lo que hice aquí es otra forma de calcular el factorial de un número entero usando un ciclo while.

def factorial(n):
    num = 1
    while n >= 1:
        num = num * n
        n = n - 1
    return num
ciziar
fuente
44
factorial (-1) devolverá 1, debería aumentar ValueError o algo así.
f.rodrigues
Esta función producirá resultados incorrectos si pasa un flotante con números después del decimal.
Boris
Con esta función, quiero imprimir factorial de los primeros cuatro enteros. Cuando cambio la num = num * nposición de la línea con n = n - 1y ejecuto esto for i in range(1, 5): print('Factorial of', i, 'is', factorial(i))Para cada factorial, la salida es 0. Me gustaría saber la razón por la que num = num * ndebe ser lo primero. ¡¡Gracias!!
18

Solución existente

La solución más corta y probablemente la más rápida es:

from math import factorial
print factorial(1000)

Construyendo tu propio

También puede crear su propia solución. Generalmente tienes dos enfoques. El que más me conviene es:

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

print factorial(1000)

(funciona también para números más grandes, cuando el resultado se convierte long)

La segunda forma de lograr lo mismo es:

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

print factorial(1000)
Tadeck
fuente
5

Si está utilizando Python2.5 o anterior, intente

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

para Python más nuevo, hay factorial en el módulo matemático como se da en otras respuestas aquí

John La Rooy
fuente
Esta es una respuesta exclusiva de Python 2, reducese eliminó de Python 3.
Boris
@ Boris, en Python3 solo necesitas agregarfrom functools import reduce
John La Rooy
Fue eliminado por una razón, no deberías usarlo 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
Jordán
fuente
4

Usando un forbucle, contando hacia atrás desde n:

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

Por motivos de rendimiento, no utilice la recursividad. Sería desastroso.

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

Verificar resultados de ejecución

cProfile.run('fact(126000)')

4 function calls in 5.164 seconds

El uso de la pila es conveniente (como una llamada recursiva), pero tiene un costo: almacenar información detallada puede ocupar mucha memoria.

Si la pila es alta, significa que la computadora almacena mucha información sobre las llamadas a funciones.

El método solo ocupa memoria constante (como la iteración).

O usando for loop

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

Verificar resultados de ejecución

cProfile.run('fact(126000)')

4 function calls in 4.708 seconds

O usando la función matemática incorporada

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

Verificar resultados de ejecución

cProfile.run('fact(126000)')

5 function calls in 0.272 seconds
binbjz
fuente
1
Creo que este bucle while parece un poco más limpio <! - language: python -> def fact (n): ret = 1 while 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

fuente
1

Aquí está mi intento

>>> 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'
Pedro Rodrigues
fuente
@Nir Levy, qué cosa tan divertida
Pedro Rodrigues el
1

Una línea, números rápidos y grandes también funciona:

#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
Jundullah
fuente
0

Sé que esto ha sido respondido, pero aquí hay otro método con una comprensión de la lista de rango inverso, lo que hace que el rango sea más fácil de leer y más compacto:

    #   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!" )

Puede ver una versión completa del código dentro de este resumen: https://gist.github.com/sadmicrowave/d4fbefc124eb69027d7a3131526e8c06

microondas
fuente
1
No es necesario usar [n for n in range(num, 0, -1)], rangeya es iterable.
Mark Mishyn
0

Otra forma de hacerlo es usar el que se np.prodmuestra a continuación:

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

Factorial de un entero positivo n, denotado por n !, es el producto de todos los enteros positivos menores o iguales a n.

Fórmula :n! = n * (n-1) * (n-2) * (n-3) * (n-4) * ....... * 1

Hay varios métodos para encontrar el factorial en python usando la función / biblioteca incorporada, etc. Aquí creé una función definida por el usuario con referencia a la definición básica de factorial.

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

print(factorial(4))

También podemos implementar la función factorial utilizando la recursivetécnica que se muestra a continuación. Pero este método solo es eficiente para valores enteros pequeños. Porque en la recursividad, la función se llama repetidamente y requiere un espacio de memoria para mantener la pila, que no es un enfoque eficiente u optimizado para valores enteros grandes para encontrar el factorial.

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

print(factorial(4))
Usman
fuente
0
def factorial(n):
mul = 1
for i in range( 1, n + 1):
    mul *= i
print(factorial(6))
Jitendra Bhalothia
fuente
Otra pregunta es qué agrega esto a las otras 17 respuestas.
pppery
Esta respuesta es un duplicado de esta respuesta existente: stackoverflow.com/a/5136481
karel
0

En el siguiente código, estoy ingresando el número cuyo factorial quiero calcular, después de eso estoy multiplicando el -> número cuyo factorial queremos calcular con números que comienzan desde 1,2, ..., (número cuyo factorial Quiero calcular -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
Rajat
fuente