J'ai besoin d'une fonction comme celle-ci:
// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true is_power_of_2(3) => false
bool is_power_of_2(int n);
Quelqu'un peut-il suggérer comment je pourrais écrire ceci? Pouvez-vous me dire un bon site Web où trouver ce type d'algorithme?
c++
algorithm
bit-manipulation
Fourmi
la source
la source
Réponses:
(n & (n - 1)) == 0
est le meilleur. Cependant, notez qu'il retournera incorrectement true pour n = 0, donc si cela est possible, vous voudrez le vérifier explicitement.http://www.graphics.stanford.edu/~seander/bithacks.html a une grande collection d'algorithmes astucieux de twiddling de bits, y compris celui-ci.
la source
(n>0 && ((n & (n-1)) == 0))
n && !(n & (n - 1))
comme le lien dans les états de réponse.n & !(n & (n - 1))
. Notez le ET au niveau du bit&
(non logique et&&
). Les opérateurs au niveau du bit n'implémentent pas de court-circuit et, par conséquent, le code ne se branche pas. Ceci est préférable dans les situations où des erreurs de prédiction de branche sont probables et lorsque le calcul des rhs de l'expression (c'est-à-dire!(n & (n - 1))
) est bon marché.!
est un opérateur logique et donc la valeur de!(n & (n - 1))
serait un booléen, êtes-vous sûr qu'un booléen et un nombre peuvent être donnés à un opérateur AND au niveau du bit? Si oui, ça a l'air bien.Une puissance de deux n'aura qu'un seul bit défini (pour les nombres non signés). Quelque chose comme
Fonctionnera très bien; un de moins qu'une puissance de deux correspond à tous les 1 dans les bits les moins significatifs, il faut donc ET à 0 au niveau du bit.
Comme je supposais des nombres non signés, le test == 0 (que j'avais oublié à l'origine, désolé) est adéquat. Vous pouvez souhaiter un test> 0 si vous utilisez des entiers signés.
la source
Les puissances de deux en binaire ressemblent à ceci:
Notez qu'il y a toujours exactement 1 bit défini. La seule exception concerne un entier signé. Par exemple, un entier signé de 8 bits avec une valeur de -128 ressemble à:
Donc, après avoir vérifié que le nombre est supérieur à zéro, nous pouvons utiliser un petit hack astucieux pour tester qu'un seul bit est défini.
Pour plus de twiddling, voir ici .
la source
Approche n ° 1:
Divisez le nombre par 2 en reclus pour le vérifier.
Complexité temporelle: O (log2n).
Approche n ° 2:
Au niveau du bit ET le nombre avec son numéro juste précédent doit être égal à ZERO.
Exemple: Nombre = 8 Binaire de 8: 1 0 0 0 Binaire de 7: 0 1 1 1 et le ET au niveau du bit des deux nombres est 0 0 0 0 = 0.
Complexité temporelle: O (1).
Approche n ° 3:
XOR au niveau du bit, le nombre avec son numéro précédent doit être la somme des deux nombres.
Exemple: Nombre = 8 Binaire de 8: 1 0 0 0 Binaire de 7: 0 1 1 1 et le XOR au niveau du bit des deux nombres est 1 1 1 1 = 15.
Complexité temporelle: O (1).
http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html
la source
la source
pour toute puissance de 2, ce qui suit vaut également.
n & (- n) == n
REMARQUE: La condition est vraie pour n = 0, bien que ce ne soit pas une puissance de 2. La
raison pour laquelle cela fonctionne est:
-n est le complément 2s de n. -n aura chaque bit à gauche du bit le plus à droite de n inversé par rapport à n. Pour les puissances de 2, il n'y a qu'un seul bit défini.
la source
En C ++ 20,
std::ispow2
vous pouvez utiliser exactement ce but si vous n'avez pas besoin de l'implémenter vous-même:la source
C'est probablement le plus rapide, si vous utilisez GCC. Il utilise uniquement une instruction de processeur POPCNT et une comparaison. Représentation binaire de toute puissance de 2 nombres, a toujours un seul bit défini, les autres bits sont toujours zéro. Nous comptons donc le nombre de bits définis avec POPCNT, et s'il est égal à 1, le nombre est une puissance de 2. Je ne pense pas qu'il y ait de méthodes plus rapides possibles. Et c'est très simple, si vous l'avez compris une fois:
la source
i && !(i & (i - 1)))
est environ 10% plus rapide sur ma machine, même si j'étais sûr d'activer l'instruction POPCNT d'assemblage native dans gcc.Le suivi serait plus rapide que la réponse la plus votée en raison du court-circuit booléen et du fait que la comparaison est lente.
Si vous savez que x ne peut pas être 0 alors
la source
la source
Si vous disposez d'un processeur Intel moderne avec les instructions de manipulation des bits , vous pouvez effectuer les opérations suivantes. Il omet le code C / C ++ simple car d'autres y ont déjà répondu, mais vous en avez besoin si l'IMC n'est pas disponible ou activé.
Prise en charge de l'IMC des signaux GCC, ICC et Clang avec
__BMI__
. Il est disponible dans les compilateurs Microsoft dans Visual Studio 2015 et versions ultérieures lorsque AVX2 est disponible et activé . Pour les en-têtes dont vous avez besoin, voir Fichiers d'en-tête pour les intrinsèques SIMD .Je garde généralement le
_blsr_u64
avec un_LP64_
en cas de compilation sur i686. Clang a besoin d'une petite solution de contournement car il utilise un nom de symbole intrinsèque légèrement différent:Ce site est souvent cité: Bit Twiddling Hacks .
la source
Ce n'est pas le moyen le plus rapide ou le plus court, mais je pense qu'il est très lisible. Donc je ferais quelque chose comme ça:
Cela fonctionne puisque le binaire est basé sur des puissances de deux. Tout nombre avec un seul bit défini doit être une puissance de deux.
la source
Voici une autre méthode, dans ce cas en utilisant
|
au lieu de&
:la source
C'est possible via c ++
la source
log2
, et la preuve que cela fonctionne n'est pas si facile à expliquer (précisément, pouvez-vous vous faire prendre par des erreurs d'arrondi?). Il est également inutilement compliqué avecif..return..else..return
. Quel est le problème avec la réductionreturn x==(double)y;
? Il devrait renvoyerbool
anyayws. OMI même opérateur ternaire serait plus clair si l'on veut vraiment s'en tenirint
.Je sais que c'est un très vieux message, mais j'ai pensé qu'il pourrait être intéressant de le publier ici.
De Code-Golf SE (donc tout le crédit à celui (s) qui a écrit ceci): Showcase of Languages
(Paragraphe sur C , sous-paragraphe Longueur 36 extrait )
la source
Une autre façon de procéder (peut-être pas la plus rapide) est de déterminer si ln (x) / ln (2) est un nombre entier.
la source
Voici la méthode de décalage de bits dans T-SQL (SQL Server):
C'est beaucoup plus rapide que de faire un logarithme quatre fois (premier ensemble pour obtenir un résultat décimal, 2ème ensemble pour obtenir un ensemble d'entiers et comparer)
la source