Incapaz de fazer uma função factorial em Python
Pergunta
Meu código
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
Eu recebo o erro
File "factorial.py", line 5
if number == 0
^
SyntaxError: invalid syntax
Como você pode fazer uma função factorial em Python?
Solução
Aqui está seu código, fixa-se e trabalhando:
import sys
number = int(sys.argv[1])
fact = 1
for x in range(1, number+1):
fact *= x
print fact
(fatorial de zero é um, para quem não sabe -. Eu tive que procurá-lo 8 -)
Você precisa de dois pontos após if
, else
, for
, etc., e as obras maneira for
em Python é diferente de C.
Outras dicas
A linha que o erro está no deve ler
if number == 0:
Note os dois pontos no final.
Além disso, você precisa adicionar o mesmo cólon após a outra e para. Os dois pontos funcionam de forma semelhante para {} em outros idiomas.
Finalmente, isso não é como para loops trabalhar em Python. O código que você deseja usar essa lista seria
for x in range(1,number):
que teria o mesmo efeito do que você escreveu, se você colocar isso em uma linguagem de estilo C.
EDIT: Opa, o loop for eu dei foi errada, ele teria incluído 0. Eu atualizei o código para corrigir este
.Eu entendo que você provavelmente está tentando implementar esse mesmo por motivos educacionais.
No entanto, se não, eu recomendo usar os módulos math
built-in função fatorial (nota: requer Python 2.6 ou superior):
>>> import math
>>> math.factorial(5)
120
Este módulo é escrito em C, e, como tal, vai ser muito, muito mais rápido do que escrevê-lo em python. (Embora, se você não está computando grandes fatoriais, não vai ser realmente muito lento de qualquer forma).
A razão Mark Rushakoff função (n) foi muito mais eficiente foi que ele perdeu-off a função de reduzir (). Assim, ele nunca realmente fez o cálculo.
Corrigido ele lê (e eu recebo):
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)))
Resultando de saída para 1.500 !, 1000x:
fact1 : 3.537624
fact1x : 4.448408
fact2 : 4.390820
fact2x : 4.333070
math.factorial : 4.091470
E sim, eu tenho verificado que todos eles deu o mesmo valor! Eu não posso entender por que o xrange lambda é muito pior do que a faixa lambda. Hmmm. Versão: PythonWin 2.6.2 (r262: 71605, 14 de abril de 2009, 22:40:02). [MSC v.1500 32 bits (Intel)] em win32
Hmm ... em re correndo-lo eu recebo algo mais crível
fact1 : 7.771696
fact1x : 7.799568
fact2 : 7.056820
fact2x : 7.247851
math.factorial : 6.875827
E em Python 2.6.5 (R265: 79063, 12 de junho de 2010, 17:07:01) [GCC 4.3.4 20.090.804 (release) 1] no cygwin:
fact1 : 6.547000
fact1x : 6.411000
fact2 : 6.068000
fact2x : 6.246000
math.factorial : 6.276000
Tudo no ruído, na verdade, não é?
Aqui está um fatorial funcional, que você quase pediu:
>>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
...
>>> fact(5)
120
Ele não funciona para fato (0), mas você pode se preocupar com isso fora do âmbito do fact
:)
Masi foi perguntado se o estilo funcional é mais eficiente que a implementação de Richie. De acordo com a minha referência rápida (e para minha surpresa!) Sim, o meu é mais rápido. Mas há algumas coisas que podemos fazer para mudar.
Em primeiro lugar, podemos substituir lambda x,y: x*y
com operator.mul
como sugerido em outro comentário. operador lambda
do Python vem com uma sobrecarga de não-insignificante. Em segundo lugar, podemos substituir xrange
para range
. xrange
deve funcionar no espaço linear, retornando números como necessário, enquanto range
cria a lista inteira de uma só vez. (Nota então, que você quase certamente deve usar xrange
para uma excessivamente grande intervalo de números)
Assim, a nova definição torna-se:
>>> import operator
>>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
...
>>> fact2(5)
120
Para minha surpresa, isso realmente resultou em um desempenho mais lento. Aqui estão os benchmarks 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
Aqui está a minha versão Python no caso de alguém quer atravessar a verificar meus resultados:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
realmente, a opção mais simples seria:
def factorial(n):
x = n
for j in range(1, n):
x = j*x
return x
Sim, de alguma forma, ele funciona.
Como é que você não acha disso? Eu não sei.
Um loop for
e um multiplicador, realmente a simplicidade é o melhor caminho a percorrer, certo?
EDIT: Oh, espere, estamos trabalhando para a forma mais cpu-efficeint? ohhhh .....