Функция для факториала в Python


Ответы:


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 >= 0и это isinstance(n, int). Если это не так, поднимите ValueErrorили TypeErrorсоответственно. math.factorialпозабочусь об этом за вас.


2
Я не понимаю, как вы можете использовать factorialв factorialфункции. Как вы можете использовать ту же функцию в функции, которую вы сейчас определяете? Я новичок в Python, поэтому я просто пытаюсь понять.
J82

8
@ J82: используемая здесь концепция называется рекурсией ( en.wikipedia.org/wiki/Recursion_(computer_science) ) - сама функция, вызывающая себя, прекрасно и часто полезна.
Schnaader

Рекурсивная функция поднимет a RecursionErrorдля любого числа больше 998 (попробуйте factorial(999)), если вы не увеличите предел рекурсии Python
Борис

114

На Python 2.6 и выше попробуйте:

import math
math.factorial(n)

Начиная с Python 3.9 , передача a floatв эту функцию вызовет a DeprecationWarning. Если вы хотите сделать это, вам нужно преобразовать nв intявно:, math.factorial(int(n))который будет отбрасывать что-либо после десятичной дроби, так что вы можете проверить этоn.is_integer()
Борис

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

Эта функция будет давать неверные результаты, если вы передадите число с плавающей запятой после десятичного числа.
Борис

С помощью этой функции я хочу распечатать факториал первых четырех целых чисел. Когда я меняю 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, в Python3 вам просто нужно добавитьfrom functools import reduce
Джон Ла

Это было удалено по причине, вы не должны использовать это artima.com/weblogs/viewpost.jsp?thread=98196
Борис


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

Использование стека удобно (например, рекурсивный вызов), но оно обходится дорого: хранение подробной информации может занимать много памяти.

Если стек высок, это означает, что компьютер хранит много информации о вызовах функций.

Метод занимает только постоянную память (как итерация).

Или Использование для цикла

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 выглядит немного чище <! - language: 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'

@ Нир Леви, какая забавная мелочь
Педро Родригес

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уже итеративный.
Марк Мишин

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.