J'ai besoin d'un moyen rapide de compter le nombre de bits dans un entier en python. Ma solution actuelle est
bin(n).count("1")
mais je me demande s'il existe un moyen plus rapide de faire cela?
PS: (je représente un grand tableau binaire 2D comme une liste unique de nombres et j'effectue des opérations au niveau du bit, ce qui réduit le temps d'heures en minutes. Et maintenant, je voudrais me débarrasser de ces minutes supplémentaires.
Edit: 1. il doit être en python 2.7 ou 2.6
et l'optimisation pour les petits nombres n'a pas beaucoup d'importance car ce ne serait pas un goulot d'étranglement clair, mais j'ai des nombres avec plus de 10000 bits à certains endroits
par exemple c'est un cas de 2000 bits:
12448057941136394342297748548545082997815840357634948550739612798732309975923280685245876950055614362283769710705811182976142803324242407017104841062064840113262840137625582646683068904149296501029754654149991842951570880471230098259905004533869130509989042199261339990315125973721454059973605358766253998615919997174542922163484086066438120268185904663422979603026066685824578356173882166747093246377302371176167843247359636030248569148734824287739046916641832890744168385253915508446422276378715722482359321205673933317512861336054835392844676749610712462818600179225635467147870208L
int
? Cela n'a-t-il pas sa propre méthode de calcul?int.bit_length
devrait être la réponse, et non celle acceptée ci-dessous.Réponses:
Pour les entiers de longueur arbitraire,
bin(n).count("1")
c'est le plus rapide que j'ai pu trouver en Python pur.J'ai essayé d'adapter les solutions d'Óscar et d'Adam pour traiter l'entier en blocs 64 bits et 32 bits, respectivement. Les deux étaient au moins dix fois plus lents que
bin(n).count("1")
(la version 32 bits a encore pris environ la moitié du temps).D'un autre côté, gmpy a
popcount()
pris environ 1 / 20e du temps debin(n).count("1")
. Donc, si vous pouvez installer gmpy, utilisez-le.Pour répondre à une question dans les commentaires, pour les octets, j'utiliserais une table de recherche. Vous pouvez le générer au moment de l'exécution:
Ou définissez-le littéralement:
Ensuite, il
counts[x]
faut obtenir le nombre de 1 bitsx
où 0 ≤ x ≤ 255.la source
bin(n).count("0")
n'est pas exact à cause du préfixe «0b». Aurait besoin d'êtrebin(n)[2:].count('0')
pour ceux qui comptent les vilaines ....numpy
tableau.bin(n).count("1")
. Cependant, ne bat que 60% de la soumission python. @ leetcodeVous pouvez adapter l'algorithme suivant:
Cela fonctionne pour les nombres positifs de 64 bits, mais il est facilement extensible et le nombre d'opérations augmente avec le logarithme de l'argument (c'est-à-dire linéairement avec la taille en bits de l'argument).
Afin de comprendre comment cela fonctionne, imaginez que vous divisez la chaîne 64 bits entière en 64 compartiments 1 bit. La valeur de chaque compartiment est égale au nombre de bits définis dans le compartiment (0 si aucun bit n'est défini et 1 si un bit est défini). La première transformation aboutit à un état analogue, mais avec 32 compartiments de 2 bits chacun. Ceci est réalisé en décalant de manière appropriée les compartiments et en ajoutant leurs valeurs (une addition prend en charge tous les compartiments car aucun report ne peut se produire entre les compartiments - un nombre de n bits est toujours assez long pour coder le nombre n). D'autres transformations conduisent à des états avec un nombre exponentiellement décroissant de seaux de taille exponentiellement croissante jusqu'à ce que nous arrivions à un seau de 64 bits de long. Cela donne le nombre de bits définis dans l'argument d'origine.
la source
CountBits()
pour gérer les nombres de 10 000 bits en ajoutant seulement 8 lignes de code. Mais cela deviendra difficile à manier en raison d'énormes constantes.numpy
tableaux.Voici une implémentation Python de l'algorithme de comptage de population, comme expliqué dans cet article :
Cela fonctionnera pour
0 <= i < 0x100000000
.la source
bin(n).count("1")
.%timeit numberOfSetBits(23544235423)
:1000000 loops, best of 3: 818 ns per loop
;%timeit bitCountStr(23544235423)
:1000000 loops, best of 3: 577 ns per loop
.numberOfSetBits
traite mes 864 × 64numpy.ndarray
en 841 µs. AvecbitCountStr
je dois boucler explicitement, et cela prend 40,7 ms, soit presque 50 fois plus longtemps.Selon cet article , cela semble être l'une des implémentations les plus rapides du poids de Hamming (si cela ne vous dérange pas d'utiliser environ 64 Ko de mémoire).
Sur Python 2.x, vous devez remplacer
range
parxrange
.Éditer
Si vous avez besoin de meilleures performances (et que vos nombres sont de gros entiers), jetez un œil à la
GMP
bibliothèque. Il contient des implémentations d'assemblage manuscrites pour de nombreuses architectures différentes.gmpy
est un module d'extension Python codé C qui encapsule la bibliothèque GMP.la source
array.array
forPOPCOUNT_TABLE16
, car elle sera stockée sous la forme d'un tableau d'entiers, au lieu d'une liste d'int
objets Python de taille dynamique .J'aime vraiment cette méthode. C'est simple et assez rapide mais pas non plus limité dans la longueur en bits puisque python a des entiers infinis.
C'est en fait plus rusé qu'il n'y paraît, car cela évite de perdre du temps à scanner les zéros. Par exemple, il faudra le même temps pour compter les bits définis dans 1000000000000000000000010100000001 que dans 1111.
la source
bin(n).count("1")
mais cela prend 3,8 s pour votre fonction. Si les nombres avaient très peu de bits, cela fonctionnerait rapidement, mais si vous prenez un nombre aléatoire, la fonction ci-dessus sera en moyenne plus lente.Vous pouvez utiliser l'algorithme pour obtenir la chaîne binaire [1] d'un entier mais au lieu de concaténer la chaîne, en comptant le nombre d'unités:
[1] https://wiki.python.org/moin/BitManipulation
la source
Vous avez dit que Numpy était trop lent. L'utilisiez-vous pour stocker des bits individuels? Pourquoi ne pas étendre l'idée d'utiliser des ints comme tableaux de bits, mais utiliser Numpy pour les stocker?
Stocke n bits sous la forme d'un tableau de
ceil(n/32.)
32 bits. Vous pouvez ensuite travailler avec le tableau numpy de la même manière (enfin assez similaire) que vous utilisez ints, y compris en les utilisant pour indexer un autre tableau.L'algorithme consiste essentiellement à calculer, en parallèle, le nombre de bits définis dans chaque cellule et à additionner le nombre de bits de chaque cellule.
Bien que je sois surpris, personne ne vous a suggéré d'écrire un module C.
la source
la source
Il s'avère que votre représentation de départ est une liste de listes d'entiers qui valent 1 ou 0. Il suffit de les compter dans cette représentation.
Le nombre de bits dans un entier est constant en python.
Cependant, si vous souhaitez compter le nombre de bits définis, le moyen le plus rapide est de créer une liste conforme au pseudocode suivant:
[numberofsetbits(n) for n in range(MAXINT)]
Cela vous fournira une recherche en temps constant après avoir généré la liste. Voir la réponse de @ PaoloMoretti pour une bonne implémentation de ceci. Bien sûr, vous n'êtes pas obligé de garder tout cela en mémoire - vous pouvez utiliser une sorte de magasin clé-valeur persistant, ou même MySql. (Une autre option serait d'implémenter votre propre stockage sur disque simple).
la source