Невозможно сделать функцию факториала в Python

StackOverflow https://stackoverflow.com/questions/1041348

  •  22-07-2019
  •  | 
  •  

Вопрос

Мой код

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?

Это было полезно?

Решение

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

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

print fact

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

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

Другие советы

Строка с вашей ошибкой должна быть прочитана

if number == 0:

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

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

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

for x in range(1,number):

Который имел бы тот же эффект, что вы написали, если бы вы поместили это на язык стилей Си.

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

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

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

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

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

Причина того, что функция факта (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

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

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

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

Это не работает для fact (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 & amp; 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

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

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

да, так или иначе, это работает.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top