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?

Foi útil?

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).

fato do

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 .....

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top