Pregunta

Mi 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

Me sale el error

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

¿Cómo puedes hacer una función factorial en Python?

¿Fue útil?

Solución

Aquí está su código, arreglado y funcionando:

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

print fact

(Factorial cero es uno, para cualquiera que no lo supiera, tuve que buscarlo. 8-)

Necesita dos puntos después de if , else , for , etc., y la forma en que for funciona Python es diferente de C.

Otros consejos

La línea en la que se encuentra su error debería leer

if number == 0:

Tenga en cuenta los dos puntos al final.

Además, necesitaría agregar los mismos dos puntos después de lo contrario y para. Los dos puntos funcionan de manera similar a {} en otros idiomas.

Finalmente, no es así como funcionan los bucles en Python. El código que desea usar en esa lista sería

for x in range(1,number):

Que tendría el mismo efecto de lo que escribiste, si lo pones en un lenguaje de estilo C.

EDITAR: ¡Vaya! El bucle for que di era incorrecto, habría incluido 0. Actualicé el código para corregir esto.

Entiendo que probablemente esté intentando implementar esto usted mismo por razones educativas.

Sin embargo, si no, recomiendo usar la función factorial incorporada de los módulos math (nota: requiere python 2.6 o superior):

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

Este módulo está escrito en C y, como tal, será mucho más rápido que escribirlo en Python. (aunque, si no está calculando factoriales grandes, no será demasiado lento de ninguna manera).

La razón por la cual la función de hecho (n) de Mark Rushakoff fue mucho más eficiente fue porque omitió la función reduce (). Por lo tanto, nunca realizó el cálculo.

Corregido se lee (y obtengo):

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

Resultado resultante para 1500 !, 1000x:

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

¡Y sí, he comprobado que todos producen el mismo valor! No puedo entender por qué el lambda xrange es mucho peor que el rango lambda. Hmmm Versión: PythonWin 2.6.2 (r262: 71605, 14 de abril de 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] en win32.

Hmm ... al volver a ejecutarlo obtengo algo más creíble

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

Y en Python 2.6.5 (r265: 79063, 12 de junio de 2010, 17:07:01) [GCC 4.3.4 20090804 (versión) 1] en cygwin:

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

Todo en el ruido realmente, ¿no?

Aquí hay un factorial funcional, que casi pediste:

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

No funciona por hecho (0), pero puede preocuparse por eso fuera del alcance de hecho :)


Masi ha preguntado si el estilo funcional es más eficiente que la implementación de Richie. Según mi punto de referencia rápido (¡y para mi sorpresa!) Sí, el mío es más rápido. Pero hay un par de cosas que podemos hacer para cambiar.

Primero, podemos sustituir lambda x, y: x * y con operator.mul como se sugiere en otro comentario. El operador lambda de Python viene con una sobrecarga no insignificante. En segundo lugar, podemos sustituir xrange por range . xrange debería funcionar en un espacio lineal, devolviendo números según sea necesario, mientras que range crea la lista completa de una vez. (Tenga en cuenta que es casi seguro que debe usar xrange para un rango de números excesivamente grande)

Entonces la nueva definición se convierte en:

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

Para mi sorpresa, esto en realidad resultó en un rendimiento más lento. Aquí están los puntos de referencia de 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

Aquí está mi versión de Python en caso de que alguien quiera verificar mis resultados:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2

realmente, la opción más simple sería:

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

sí, de alguna manera, funciona.

¿Cómo no pensar en esto? No lo se.

Un bucle for y un multiplicador, realmente la simplicidad es la mejor manera de hacerlo, ¿no?

EDITAR: Oh, espera, ¿estamos trabajando para la manera más eficiente de la CPU? ohhhh .....

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top