Невозможно сделать функцию факториала в Python - PullRequest
0 голосов
/ 25 июня 2009

Мой код

import sys

number=int(sys.argv[1])

if number == 0
    fact=1
else
    fact=number
for (x=1; x<number; x++)
    fact*=x;             // mistake probably here

print fact

Я получаю ошибку

File "factorial.py", line 5
    if number == 0
                 ^
SyntaxError: invalid syntax

Как сделать факториальную функцию в Python?

Ответы [ 6 ]

12 голосов
/ 25 июня 2009

Строка, в которой указана ваша ошибка, должна выглядеть так:

if number == 0:

Обратите внимание на двоеточие на конце.

Кроме того, вам необходимо добавить такое же двоеточие после else и for. Двоеточия работают аналогично {} в других языках.

Наконец, это не то, как циклы работают в Python. Код, который вы хотите использовать в этом списке, будет

for x in range(1,number):

Что будет иметь тот же эффект, что вы написали, если вы поместите это на язык стиля C.

РЕДАКТИРОВАТЬ: К сожалению, цикл for, который я дал, был неправильным, он включал бы 0. Я обновил код, чтобы исправить это.

9 голосов
/ 25 июня 2009

Я понимаю, что вы, вероятно, пытаетесь реализовать это самостоятельно в образовательных целях.

Однако, если нет, я рекомендую использовать встроенную факториальную функцию модулей math (примечание: требуется python 2.6 или выше):

>>> import math
>>> math.factorial(5)
120

Этот модуль написан на C, и поэтому он будет намного быстрее, чем на Python. (хотя, если вы не вычисляете большие факториалы, в любом случае это не будет слишком медленным).

8 голосов
/ 25 июня 2009

Вот ваш код, исправленный и работающий:

import sys
number = int(sys.argv[1])
fact = 1
for x in range(1, number+1):
    fact *= x

print fact

(Факторный ноль равен единице, для тех, кто не знал - мне пришлось это искать. 8 -)

Вам нужны двоеточия после if, else, for и т. Д., А способ for в Python отличается от C.

3 голосов
/ 07 октября 2010

Причина того, что функция факта (n) Марка Рушакова была гораздо более эффективной, заключалась в том, что он пропустил функцию redu (). Таким образом, он никогда не делал вычисления.

Исправлено это читает (и я получаю):

import operator, timeit, math
#
def fact1(n):  return reduce(lambda x,y: x*y,  range(1,n+1),1)
def fact1x(n): return reduce(lambda x,y: x*y, xrange(1,n+1),1)
def fact2(n):  return reduce(operator.mul   ,  range(1,n+1),1)
def fact2x(n): return reduce(operator.mul   , xrange(1,n+1),1)
#
def factorialtimer():
    for myfunc in [ "fact1", "fact1x", "fact2", "fact2x" ]:
        mytimer = timeit.Timer(myfunc+"(1500)", "from __main__ import "+myfunc)
        print("{0:15} : {1:2.6f}".format(myfunc, mytimer.timeit(number=1000)))

    mytimer = timeit.Timer("factorial(1500)", "from math import factorial")
    print("{0:15} : {1:2.6f}".format("math.factorial", mytimer.timeit(number=1000)))

Результирующий вывод для 1500 !, 1000x:

fact1           : 3.537624
fact1x          : 4.448408
fact2           : 4.390820
fact2x          : 4.333070
math.factorial  : 4.091470

И да, я проверил, что все они дают одинаковое значение! Я не могу понять, почему лямбда-xrange намного хуже, чем лямбда-диапазон. Хммм. Версия: PythonWin 2.6.2 (r262: 71605, 14 апреля 2009, 22:40:02) [MSC v.1500 32 бит (Intel)] на win32.

Хм ... при повторном запуске я получаю что-то более правдоподобное

fact1           : 7.771696
fact1x          : 7.799568
fact2           : 7.056820
fact2x          : 7.247851
math.factorial  : 6.875827

И на Python 2.6.5 (r265: 79063, 12 июня 2010, 17:07:01) [GCC 4.3.4 20090804 (выпуск) 1] на cygwin:

fact1           : 6.547000
fact1x          : 6.411000
fact2           : 6.068000
fact2x          : 6.246000
math.factorial  : 6.276000

Все на самом деле в шуме, не так ли?

2 голосов
/ 25 июня 2009

Вот функциональный факториал, который вы почти просили:

>>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
... 
>>> fact(5)
120

Фактически это не работает (0), но вы можете беспокоиться об этом за пределами fact:)


Маси спросил, является ли функциональный стиль более эффективным, чем реализация Ричи. Согласно моему быстрому тесту (и, к моему удивлению!), Да, мой быстрее. Но есть пара вещей, которые мы можем сделать, чтобы измениться.

Во-первых, мы можем заменить lambda x,y: x*y на operator.mul, как предлагается в другом комментарии. Оператор Python lambda имеет незначительные накладные расходы. Во-вторых, мы можем заменить xrange на range. xrange должен работать в линейном пространстве, возвращая числа по мере необходимости, тогда как range создает весь список сразу. (Обратите внимание, что вы почти наверняка должны использовать xrange для слишком большого диапазона чисел)

Таким образом, новое определение становится:

>>> import operator
>>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
... 
>>> fact2(5)
120

К моему удивлению, это фактически привело к снижению производительности. Вот тесты Q & D:

>>> def fact(n): return (lambda x,y: x*y, range(1,n+1))
... 
>>> t1 = Timer("fact(500)", "from __main__ import fact")
>>> print t1.timeit(number = 500)
0.00656795501709

>>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
...
>>> t2 = Timer("fact2(500)", "from __main__ import fact2")
>>> print t2.timeit(number = 500)
0.35856294632

>>> def fact3(n): return reduce(operator.mul, range(1,n+1))
... 
>>> t3 = Timer("fact3(500)", "from __main__ import fact3")
>>> print t3.timeit(number = 500)
0.354646205902

>>> def fact4(n): return reduce(lambda x,y: x*y, xrange(1,n+1))
... 
>>> t4 = Timer("fact4(500)", "from __main__ import fact4")
>>> print t4.timeit(number = 500)
0.479015111923

>>> def fact5(n):
...     x = 1
...     for i in range(1, n+1):
...             x *= i
...     return x
... 
>>> t5 = Timer("fact5(500)", "from __main__ import fact5")
>>> print t5.timeit(number = 500)
0.388549804688

Вот моя версия Python на случай, если кто-нибудь захочет перепроверить мои результаты:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
1 голос
/ 16 декабря 2011

действительно, самый простой вариант будет:

def factorial(n):
    x = n
    for j in range(1, n):
        x = j*x
    return x

да, как-то, это работает.

Как ты мог не думать об этом? Я не знаю.

Цикл for и множитель, действительно, простота - лучший путь

РЕДАКТИРОВАТЬ: Ой, подождите, мы работаем для наиболее процессорным способом? Оооо .....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...