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ù ce type d'algorithme peut être trouvé?
(n & (n - 1)) == 0
est le meilleur. Cependant, notez qu'il renverra incorrectement la valeur true pour n = 0; par conséquent, si cela est possible, vous souhaiterez le vérifier explicitement.
http://www.graphics.stanford.edu/~seander/bithacks.html possède une vaste collection d’algorithmes intelligents, notamment celui-ci.
Une puissance de deux n'aura qu'un bit défini (pour les nombres non signés). Quelque chose comme
bool powerOfTwo = !(x == 0) && !(x & (x - 1));
Fonctionnera bien; un de moins qu'une puissance de deux correspond à tous les 1 dans les bits les moins significatifs; il en va donc de même pour AND à 0 bits.
Comme je supposais des nombres non signés, le test == 0 (que j'avais initialement oublié, désolé) est adéquat. Vous voudrez peut-être un test> 0 si vous utilisez des entiers signés.
Les puissances de deux en binaire ressemblent à ceci:
1: 0001
2: 0010
4: 0100
8: 1000
Notez qu'il y a toujours exactement 1 bit défini. La seule exception est avec un entier signé. par exemple. Un entier signé de 8 bits avec une valeur de -128 se présente comme suit:
10000000
Ainsi, après avoir vérifié que le nombre est supérieur à zéro, nous pouvons utiliser un petit bidouillage astucieux pour vérifier qu'un seul bit est activé.
bool is_power_of_2(int x) {
return x > 0 && !(x & (x−1));
}
Pour plus de bricolage, voir ici .
Approche n ° 1:
Divisez le nombre par 2 de manière reclus pour le vérifier.
Complexité temporelle: O (log2n).
Approche n ° 2:
Au niveau des bits 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 AND au niveau des bits des deux nombres est 0 0 0 0 = 0.
Complexité temporelle: O (1).
Approche n ° 3:
Au niveau du bit XOR, le nombre avec son numéro juste 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 bitwise XOR des deux nombres est 1 1 1 1 1 = 15 .
Complexité temporelle: O (1).
http://javaexplorer03.blogspot.in/2016/01/how-to-check-number-is-power-of-two.html
bool is_power_of_2(int i) {
if ( i <= 0 ) {
return 0;
}
return ! (i & (i-1));
}
pour toute puissance de 2, ce qui suit est également valable.
NOTE: 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 à 2 de n. -n aura tous les bits situés à gauche du bit défini le plus à droite de n retourné par rapport à n. Pour des puissances de 2, il n'y a qu'un seul bit défini.
return n > 0 && 0 == (1 << 30) % n;
Quel est le moyen le plus simple de tester si un nombre est une puissance de 2 en C++?
Si vous avez un processeur Intel moderne avec Instructions de manipulation de bits , vous pouvez alors procéder comme suit. Il omet le code simple C/C++ car d’autres y ont déjà répondu, mais vous en avez besoin si l’IMC n’est pas disponible ou activé.
bool IsPowerOf2_32(uint32_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
return !!((x > 0) && _blsr_u32(x));
#endif
// Fallback to C/C++ code
}
bool IsPowerOf2_64(uint64_t x)
{
#if __BMI__ || ((_MSC_VER >= 1900) && defined(__AVX2__))
return !!((x > 0) && _blsr_u64(x));
#endif
// Fallback to C/C++ code
}
GCC, ICC et Clang signalent la prise en charge de BMI 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 composants intrinsèques SIMD .
Je garde habituellement le _blsr_u64
avec un _LP64_
en cas de compilation sur i686. Clang nécessite un peu de solution de contournement, car il utilise un nom de symbole intrinsèque légèrement différent:
#if defined(__GNUC__) && defined(__BMI__)
# if defined(__clang__)
# ifndef _tzcnt_u32
# define _tzcnt_u32(x) __tzcnt_u32(x)
# endif
# ifndef _blsr_u32
# define _blsr_u32(x) __blsr_u32(x)
# endif
# ifdef __x86_64__
# ifndef _tzcnt_u64
# define _tzcnt_u64(x) __tzcnt_u64(x)
# endif
# ifndef _blsr_u64
# define _blsr_u64(x) __blsr_u64(x)
# endif
# endif // x86_64
# endif // Clang
#endif // GNUC and BMI
Pouvez-vous me dire un bon site web où ce type d'algorithme peut être trouvé?
Ce site Web est souvent cité: Bit Twiddling Hacks .
Suivre serait plus rapide que la réponse la plus favorable en raison du court-circuitage booléen et du fait que la comparaison est lente.
int isPowerOfTwo(unsigned int x)
{
return x && !(x & (x – 1));
}
Si vous savez que x ne peut pas être 0 alors
int isPowerOfTwo(unsigned int x)
{
return !(x & (x – 1));
}
En C++ 20, il existe std::ispow2
que vous pouvez utiliser exactement à cette fin si vous n'avez pas besoin de l'implémenter vous-même:
_#include <bit>
static_assert(std::ispow2(16));
static_assert(!std::ispow2(15));
_
Ce n'est pas le moyen le plus rapide ou le plus rapide, mais je pense que c'est très lisible. Donc je ferais quelque chose comme ça:
bool is_power_of_2(int n)
int bitCounter=0;
while(n) {
if ((n & 1) == 1) {
++bitCounter;
}
n >>= 1;
}
return (bitCounter == 1);
}
Cela fonctionne car le binaire est basé sur des puissances de deux. Tout nombre avec un seul bit défini doit être une puissance de deux.
C'est le plus rapide:
if(1==__builtin_popcount(n))
Voici une autre méthode, dans ce cas, utilisez |
au lieu de &
:
bool is_power_of_2(int x) {
return x > 0 && (x<<1 == (x|(x-1)) +1));
}
C'est possible avec c ++
int IsPowOf2(int z) {
double x=log2(z);
int y=x;
if (x==(double)y)
return 1;
else
return 0;
}