Domanda

Il mio codice

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

Ottengo l'errore

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

Come puoi fare una funzione fattoriale in Python?

È stato utile?

Soluzione

Ecco il tuo codice, corretto e funzionante:

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

print fact

(Lo zero fattoriale è uno, per chiunque non lo sapesse, ho dovuto cercarlo. Cool

Sono necessari due punti dopo se , else , per , ecc. e il modo in cui per funziona Python è diverso da C.

Altri suggerimenti

La riga su cui si trova il tuo errore dovrebbe essere letta

if number == 0:

Nota i due punti alla fine.

Inoltre, dovrai aggiungere gli stessi due punti dopo l'altro e il per. I due punti funzionano in modo simile a {} in altre lingue.

Infine, non è così che i loop funzionano in Python. Il codice che si desidera utilizzare tale elenco sarebbe

for x in range(1,number):

Che avrebbe lo stesso effetto di quello che hai scritto, se lo mettessi in un linguaggio in stile C.

EDIT: Oops, il ciclo for che ho dato era sbagliato, avrebbe incluso 0. Ho aggiornato il codice per correggere questo.

Capisco che probabilmente stai cercando di implementarlo da solo per motivi educativi.

Tuttavia, in caso contrario, raccomando di utilizzare la funzione fattoriale integrata dei moduli math (nota: richiede python 2.6 o successivo):

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

Questo modulo è scritto in C e, come tale, sarà molto più veloce di scriverlo in Python. (anche se, se non stai calcolando fattoriali di grandi dimensioni, non sarà davvero troppo lento in entrambi i modi).

Il motivo per cui la funzione fact (n) di Mark Rushakoff era molto più efficiente è che ha perso la funzione di riduzione (). Quindi non ha mai effettivamente effettuato il calcolo.

Corretto, legge (e ottengo):

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

Output risultante per 1500 !, 1000x:

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

E sì, ho verificato che producono tutti lo stesso valore! Non riesco a capire perché la lambda xrange sia molto peggio della gamma lambda. Hmmm. Versione: PythonWin 2.6.2 (r262: 71605, 14 aprile 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] su win32.

Hmm ... nel rieseguirlo ottengo qualcosa di più credibile

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

E su Python 2.6.5 (r265: 79063, 12 giugno 2010, 17:07:01) [GCC 4.3.4 20090804 (versione) 1] su cygwin:

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

Tutto davvero nel rumore, vero?

Ecco un fattoriale funzionale, che hai quasi chiesto:

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

Non funziona per i fatti (0), ma puoi preoccupartene al di fuori dell'ambito di fact :)


Masi ha chiesto se lo stile funzionale è più efficiente dell'implementazione di Richie. Secondo il mio rapido benchmark (e con mia sorpresa!) Sì, il mio è più veloce. Ma ci sono un paio di cose che possiamo fare per cambiare.

Innanzitutto, possiamo sostituire lambda x, y: x * y con operator.mul come suggerito in un altro commento. L'operatore lambda di Python ha un overhead non insignificante. In secondo luogo, possiamo sostituire xrange con range . xrange dovrebbe funzionare nello spazio lineare, restituendo i numeri se necessario, mentre range crea l'intero elenco in una sola volta. (Nota quindi che quasi certamente devi usare xrange per un intervallo di numeri eccessivamente ampio)

Quindi la nuova definizione diventa:

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

Con mia sorpresa, ciò ha comportato prestazioni più lente. Ecco i benchmark 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

Ecco la mia versione di Python nel caso in cui qualcuno volesse fare un controllo incrociato dei miei risultati:

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

davvero, l'opzione più semplice sarebbe:

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

sì, in qualche modo, funziona.

Come hai potuto non pensarci? Non lo so.

Un ciclo per e un moltiplicatore, davvero la semplicità è il modo migliore di procedere, giusto?

EDIT: Oh, aspetta, stiamo lavorando per il modo più efficace di cpu? ohhhh .....

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top