Il semble que la plage est connue . Supposons que cela va jusqu'à 1 < < 20, juste pour le rendre plus intéressant:
max_log2=20
donc faire une liste (en vigueur) mappe un nombre entier à son logarithme en base 2. Ce qui suit fera l'affaire:
log2s_table=[0]*((1<<max_log2)+1)
for i in range(max_log2+1):
log2s_table[1<<i]=i
(Cela ne fait pas quelque chose d'utile pour les numéros qui ne sont pas des puissances de deux, l'énoncé du problème suggère qu'ils ne doivent pas être manipulés serait assez facile. résoudre ce problème si)
la fonction pour obtenir le logarithme est très simple, et pourrait facilement être inline.
def table(v):
return log2s_table[v]
Je ne peux pas garantir que le code de test je l'ai écrit est exactement le même que celui étant utilisé pour obtenir les timings d'exemple, mais c'est plutôt plus rapide que leCode:
stringcount: 0.43 s.
table: 0.16 s.
Puisque toutes les valeurs du tableau sont inférieurs à 256, je me demandais si l'aide d'une chaîne au lieu d'une liste serait plus rapide, ou peut-être un array.array
d'octets, mais pas de dés:
string: 0.25 s.
arr: 0.21 s.
l'utilisation d'un dict
pour faire la recherche est une autre possibilité, en profitant de la manière que des puissances de deux sont en cours de vérification:
log2s_map=dict([(1<<x,x) for x in range(max_log2+1)])
def map(v):
return log2s_map[v]
Les résultats de ce ne sont pas aussi bien, si:
map: 0.20 s.
Et juste pour le plaisir on pourrait également utiliser la méthode hex
sur des objets flottants pour obtenir une chaîne qui comprend (comme sa dernière partie) la base 2 exposant le nombre.Ceci est un peu lent à extraire en général, mais si l'exposant n'est jamais va être un chiffre, il pourrait se faire assez sans détour:
def floathex(v):
return ord(float(v).hex()[-1])-48
Ceci est purement pour la valeur de divertissement mais comme il était uncompetetive - si , étonnamment, toujours plus rapide que l'approche bitwise.
il ressemble à l'aide d'une liste est le chemin à parcourir. (Cette approche ne sera pas mise à l'échelle indéfiniment, en raison de la mémoire limitée, mais pour compenser que la vitesse d'exécution ne dépendra pas de max_log2
, ou des valeurs d'entrée, de quelque façon que vous remarquerez lors de l'exécution de python code. en ce qui concerne la consommation de mémoire, si je me souviens bien mes internals python, la table prendra environ (1<<max_log2)*4
octets, car le contenu sont tous petits entiers que l'interprète stagiaire automatiquement. Donc, quand max_log2
est 20, qui est à peu près 4Mo.)
Je voulais juste ajouter deux références. Le premier, Fast Bytecodes for Funny Languages de Cliff Cock, http://www.infoq.com/presentations/click-fast-bytecodes-funny-languages du JVM Languages Summit 2008, qui aborde les optimisations utilisées et manquées par les langues «moins courantes» . Le second est état des astuces d'optimisation du compilateur C art http://lambda-the-ultimate.org/node/3674 par Felix von Leitner, présenté à Linux Kongress 2009, il couvre la façon intelligente votre compilateur (environnement) est ces jours-ci, et pourquoi vous devriez être très prudent en supposant que vous devez utiliser des astuces de style Michael Abrash. – mctylr
@mctylr - Merci pour les références (+1) – mac