Avevo fatto un test, prima di vedere la tua risposta, chiedendomi se potevo dimostrare a suon di esempio quel che pensavo. Allego il codice. Salta fuori che randint()|1 e' in effetti meno efficiente di randrange ma, secondo me, non per l'uso del | , ma per come e' implementata la randint() stessa. ho fatto randspeed2.py <Massimo> <numero_iterazioni> e mi risulta questo:
con 100 come massimo e 1e6 iterazioni: m...@myhost:~$ python randspeed2.py 100 1000000 con randint(0,Rmax)|1 tempo = 7.436640 con randrange(1,Rmax=1,2) tempo = 6.940893 con choiche(...) tempo = 3.326678 con int(random.rand()*Rmax)|1 tempo = 2.339324 con 1e6 come massimo e 1e6 iterazioni: m...@myhost:~$ python randspeed2.py 1000000 1000000 con randint(0,Rmax)|1 tempo = 8.687074 con randrange(1,Rmax=1,2) tempo = 8.094956 con choiche(...) tempo = 5.408784 con int(random.rand()*Rmax)|1 tempo = 2.754338 Salta fuori che int(random.rand()*Rmax)|1 batte la concorrenza in modo abbastanza vistoso, oltre a richiedere meno risorse in assoluto (puo' capitare che python giri in ambiente dove risparmiare memoria e' importante). Quanto al | in se, per me e' un operatore python, tanto come + e deve essere, per me, tanto leggibile quanto gli altri operatori. Naturalmente rispetto le tue preferenze. Ciao e grazie per la discussione Stefano 2010/1/5 Enrico Franchi <enrico.fran...@gmail.com>: > > On Jan 5, 2010, at 1:01 PM, Stefano Dal Pra wrote: > >> Perche' quella e' pura e semplice sintassi python, quindi legittima. > > Attenzione ad usare il termine "sintassi" a sproposito. > Tutta e' "sintassi" python, se non sarebbe rifiutata dal compilatore > e saremmo in presenza di programmi non ben formati. > >> Poi per motivi di efficienza: >> l'interprete, se non e' scemo, dovrebbe tradurre il | 1 con una >> singola istruzione macchina (or bit a bit). Se devi generare un >> dispari e via, ok. Se ne devi fare moltissimi e piu' rapidamente >> possibile, il discorso cambia. > > Ho smesso nel credere alle misure spannometriche. > > 1. assumi che la macchina virtuale Python *sia* scema > 2. in generale in Python e' l'astrazione a pagare, non il dettaglio a basso > livello. > > Quindi, se voglio dire che "una cosa e' piu' veloce di un'altra" la misuro. > Finche' non mi sono reso conto che *ho* un problema di performance, la cosa > non la valuto neppure. > Se la valuto, la valuto in modo oggettivo, controllato, misurato. Cerco il > collo di bottiglia > e non intervengo "a caso". Trovato il collo di bottiglia, si valuta se lo > speedup atteso > sia comparabile con il peggioramento del codice oppure se non sia possibile > un intervento > architetturale piu' efficiente ancora. > > A questo punto si procede, misurando attentamente i vantaggi in termini di > performance. > > In particolare, nel nostro specifico caso, salta fuori che il metodo > suggerito da Marco > sia *piu' veloce* di quello suggerito da te, che asserisci essere piu' veloce > non mi > e' chiaro sulla base di cosa. > > % /usr/bin/python2.6 oddrandom.py > baseline : 0.0180490016937 > bit manip: 2.38537406921 > randrange: 2.28163599968 > > > Certo, non *molto* piu' veloce. Su un milione di esecuzioni circa un decimo > di secondo. > Fossero stati i risultati invertiti, non mi sarei preoccupato ugualmente. > > Quindi, di fatto e' il classico esempio di ottimizzazione prematura. Anzi, > un'ottimizzazione > che *peggiora* le performance (e la leggibilita'). > > Tra l'altro, quando si fanno simulazioni numeriche, spesso si accetta di > rifare piu' volte > gli esperimenti (quindi "di fatto" peggiorando il tempo di esecuzione di un > fattore lineare) > pur di provarli con diversi generatori di numeri per mettersi al riparo da > problemi di > non troppo pseudo-casualita'. Quindi, figuriamoci. :) > > >> Per non giocare con i bit uno puo' fare randint(0,4) * 2 + 1 e ottiene >> i dispari tra 1 e 9, tanto equiprobabili quanto randint(0,4). >> Nel caso di randint(0,9) | 1 , ogni risultato ha esattamente due >> possibilita' di uscire: era il pari immediatamente superiore a cui si >> e' aggiunto 1, oppure era direttamente dispari, e non e' cambiato. > > No, hai *perso* informazione. Eventualmente una quantita' completamente > trascurabile, > possibilmente una quantita' rilevante. Con la semplice assunzione che ognuno > dei > 32 bit sia responsabile per 1/32 della qi, il primo modo fa una > trasformazione lineare > (e quindi di fatto anche la qi rimane invariata). Con il tuo trucco invece > perdi 1/32 della > qi. Non tanto, ma nemmeno poco. Dopotutto, visto che si puo' evitare il tutto. > > Questo *a monte* del fatto che stai scegliendo su un range ristretto di > numeri, eh. > _______________________________________________ > Python mailing list > Python@lists.python.it > http://lists.python.it/mailman/listinfo/python >
#!/usr/bin/env python import time,random,sys n,iter,T=0,0,[] Rmax=int(sys.argv[1]) itermax=int(sys.argv[2]) T0=time.time() while iter<itermax: n=random.randint(0,Rmax)|1 iter+=1 T1=time.time() print "con randint(0,Rmax)|1 tempo = %f"%(T1-T0) iter=0 T2=time.time() while iter<itermax: n=random.randrange(1,Rmax+1,2) iter+=1 T3=time.time() print "con randrange(1,Rmax=1,2) tempo = %f"%(T3-T2) iter=0 T4=time.time() R=range(1,Rmax+1,2) while iter<itermax: n=random.choice(R) iter+=1 T5=time.time() print "con choiche(...) tempo = %f"%(T5-T4) iter=0 T6=time.time() Rmax-=1 while iter<itermax: n=int(random.random()*Rmax)|1 iter+=1 T7=time.time() print "con int(random.rand()*Rmax)|1 tempo = %f"%(T7-T6)
_______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python