Chức năng cho nhân tố trong Python


135

Làm thế nào để tôi đi về tính toán một giai thừa của một số nguyên trong Python?

Câu trả lời:


191

Cách dễ nhất là sử dụng math.factorial(có sẵn trong Python 2.6 trở lên):

import math
math.factorial(1000)

Nếu bạn muốn / phải tự viết nó, bạn có thể sử dụng phương pháp lặp:

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

hoặc một cách tiếp cận đệ quy :

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

Lưu ý rằng hàm giai thừa chỉ được xác định cho các số nguyên dương, do đó bạn cũng nên kiểm tra điều đó n >= 0và đó isinstance(n, int). Nếu không, tăng một ValueErrorhoặc TypeErrortương ứng. math.factorialsẽ chăm sóc điều này cho bạn.


2
Tôi không hiểu làm thế nào bạn có thể sử dụng factorialtrong factorialchức năng. Làm thế nào bạn có thể sử dụng cùng một chức năng trong chức năng bạn hiện đang xác định? Tôi mới sử dụng Python nên tôi chỉ đang cố hiểu.
J82

8
@ J82: Khái niệm được sử dụng ở đây được gọi là đệ quy ( en.wikipedia.org/wiki/Recursion_(computer_science) ) - một hàm tự gọi là hoàn toàn tốt và thường hữu ích.
schnaader

Hàm đệ quy sẽ tăng một số RecursionErrorcho bất kỳ số nào lớn hơn 998 (thử factorial(999)) trừ khi bạn tăng giới hạn đệ quy của Python
Boris

114

Trên Python 2.6 trở lên, hãy thử:

import math
math.factorial(n)

Bắt đầu với Python 3.9 , việc truyền a floatđến hàm này sẽ tăng a DeprecationWarning. Nếu bạn muốn làm điều đó, bạn cần chuyển đổi nthành một intcách rõ ràng : math.factorial(int(n)), nó sẽ loại bỏ bất cứ thứ gì sau số thập phân, vì vậy bạn có thể muốn kiểm tra điều đón.is_integer()
Boris

25

Không thực sự cần thiết vì đây là một chủ đề cũ. Nhưng tôi đã làm ở đây là một cách khác để tính giai thừa của một số nguyên bằng cách sử dụng vòng lặp while.

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

4
giai thừa (-1) sẽ trả về 1, nên tăng ValueError hoặc một cái gì đó.
f.rodrigues

Hàm này sẽ tạo ra kết quả không chính xác nếu bạn vượt qua một số float sau số thập phân.
Boris

Với chức năng này, tôi muốn in giai thừa của bốn số nguyên đầu tiên. Khi tôi trao đổi num = num * nvị trí dòng với n = n - 1và chạy cái này for i in range(1, 5): print('Factorial of', i, 'is', factorial(i))Đối với mỗi Factorial, đầu ra là 0. Tôi muốn biết lý do tại sao num = num * ncần phải đến trước. Cảm ơn!!

18

Giải pháp hiện có

Giải pháp ngắn nhất và có lẽ là nhanh nhất là:

from math import factorial
print factorial(1000)

Xây dựng của riêng bạn

Bạn cũng có thể xây dựng giải pháp của riêng bạn. Nói chung bạn có hai cách tiếp cận. Thứ phù hợp với tôi nhất là:

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

print factorial(1000)

(nó cũng hoạt động với số lượng lớn hơn, khi kết quả trở thành long)

Cách thứ hai để đạt được điều tương tự là:

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

print factorial(1000)


5

Nếu bạn đang sử dụng Python2.5 trở lên hãy thử

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

đối với Python mới hơn, có mô-đun trong mô-đun toán học như được đưa ra trong các câu trả lời khác ở đây


Đây là câu trả lời chỉ dành cho Python 2, reduceđã bị xóa khỏi Python 3.
Boris

@Boris, trong Python3 bạn chỉ cần thêmfrom functools import reduce
John La Rooy

Nó đã bị xóa vì một lý do, bạn không nên sử dụng nó 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

Sử dụng một for-loop, đếm ngược từ n:

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

3

Vì lý do hiệu suất, xin vui lòng không sử dụng đệ quy. Nó sẽ là thảm họa.

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

Kiểm tra kết quả chạy

cProfile.run('fact(126000)')

4 function calls in 5.164 seconds

Sử dụng ngăn xếp là thuận tiện (như cuộc gọi đệ quy), nhưng nó có chi phí: lưu trữ thông tin chi tiết có thể chiếm rất nhiều bộ nhớ.

Nếu ngăn xếp cao, điều đó có nghĩa là máy tính lưu trữ rất nhiều thông tin về các cuộc gọi chức năng.

Phương thức chỉ chiếm bộ nhớ không đổi (như lặp).

Hoặc sử dụng cho vòng lặp

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

Kiểm tra kết quả chạy

cProfile.run('fact(126000)')

4 function calls in 4.708 seconds

Hoặc sử dụng toán học hàm dựng sẵn

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

Kiểm tra kết quả chạy

cProfile.run('fact(126000)')

5 function calls in 0.272 seconds

1
Tôi nghĩ vòng lặp while này trông gọn gàng hơn một chút <! - ngôn ngữ: 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

1

Đây là cố gắng của tôi

>>> 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, thật là một điều thú vị nho nhỏ
Pedro

1

Một dòng, số nhanh và lớn cũng hoạt động:

#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

Tôi biết điều này đã được trả lời nhưng đây là một phương pháp khác với cách hiểu danh sách phạm vi ngược, làm cho phạm vi dễ đọc hơn và gọn hơn:

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

Bạn có thể xem phiên bản đầy đủ của mã trong ý chính này: https://gist.github.com/sadmic [/ d4fbefc124eb69027d7a3131526e8c06


1
Không cần sử dụng [n for n in range(num, 0, -1)], rangeđã lặp lại.
Đánh dấu Mishyn

0

Một cách khác để làm điều đó là sử dụng np.prodhiển thị dưới đây:

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

0

yếu tố số của một số nguyên dương n, ký hiệu là n!, Là tích của tất cả các số nguyên dương nhỏ hơn hoặc bằng n.

Công thức :n! = n * (n-1) * (n-2) * (n-3) * (n-4) * ....... * 1

Có một số phương pháp để tìm giai thừa trong python bằng cách sử dụng hàm dựng / thư viện dựng sẵn, v.v ... Ở đây tôi đã tạo hàm do người dùng định nghĩa với tham chiếu định nghĩa cơ bản của giai thừa.

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

print(factorial(4))

Chúng ta cũng có thể thực hiện chức năng giai thừa bằng cách sử dụng recursivekỹ thuật như dưới đây. Nhưng phương pháp này chỉ hiệu quả đối với các giá trị nguyên nhỏ. Bởi vì trong đệ quy, hàm được gọi liên tục & yêu cầu một không gian bộ nhớ để duy trì ngăn xếp không phải là cách tiếp cận hiệu quả hoặc tối ưu hóa cho các giá trị số nguyên lớn để tìm giai thừa.

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

print(factorial(4))


0

Trong đoạn mã dưới đây, tôi lấy đầu vào của số mà nhân tử tôi muốn tính, Sau đó tôi nhân số -> số có nhân tử mà chúng tôi muốn tính với các số bắt đầu từ 1,2, ...., (số có giai thừa Tôi muốn tính -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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.