Функція для Factorial в Python


135

Як мені зайнятися обчисленням коефіцієнта цілого числа в 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) ) - функція, яка називає себе, є цілком тонкою і часто корисною.
шнадер

Рекурсивна функція підвищить а RecursionErrorдля будь-якого числа, що перевищує 998 (спробуйте factorial(999)), якщо ви не збільшите межу рекурсії Python
Борис

114

На Python 2.6 і новіших версіях спробуйте:

import math
math.factorial(n)

Починаючи з Python 3.9 , перехід floatдо цієї функції призведе до а 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
факториал (-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
Я думаю, що це в той час як цикл виглядає трохи чистіше <! - мова: python -> def fact (n): ret = 1, а n> 1: n, ret = n - 1, ret * n повернення 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, яка прикольна штука
Педро Родрігес

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.