Je dois dire que je n'ai jamais eu de raison d'utiliser des opérateurs au niveau du bit, mais je suis sûr que j'ai effectué certaines opérations qui auraient été plus efficaces avec eux. Comment le "décalage" et la "RO" vous ont-ils aidé à résoudre un problème plus efficacement?
Voir le célèbre Bit Twiddling Hacks
La plupart des multiplications/divisions ne sont pas nécessaires - le compilateur le fera automatiquement et vous ne ferez que confondre les gens.
Mais il existe un tas de hacks de type "vérifier/définir/basculer le bit N" qui sont très utiles si vous travaillez avec du matériel ou des protocoles de communication.
Convertir la lettre en en minuscules:
OR
par espace => (x | ' ')
('a' | ' ') => 'a'
; ('A' | ' ') => 'a'
Convertir la lettre en en majuscules:
AND
par souligné => (x & '_')
('a' & '_') => 'A'
; ('A' & '_') => 'A'
Inverser casse de la lettre:
XOR
par espace => (x ^ ' ')
('a' ^ ' ') => 'A'
; ('A' ^ ' ') => 'a'
Lettre position dans l'alphabet:
AND
par chr(31)
/binary('11111')
/(hex('1F')
=> (x & "\x1F")
('a' & "\x1F") => 1
; ('B' & "\x1F") => 2
Récupère la lettre position dans l'alphabet (pour majuscule lettres uniquement):
AND
par ?
=> (x & '?')
ou = XOR
par @
=> (x ^ '@')
('C' & '?') => 3
; ('Z' ^ '@') => 26
Récupère la lettre position dans l'alphabet (pour minuscule lettres uniquement):
XOR
par backtick/chr(96)
/binary('1100000')
/hex('60')
=> (x ^ '`')
('d' ^ '`') => 4
; ('x' ^ '`') => 25
Remarque: utiliser autre chose que les lettres anglaises produira des résultats inutiles
Obtenez l'entier maximum
int maxInt = ~(1 << 31);
int maxInt = (1 << 31) - 1;
int maxInt = (1 << -1) - 1;
Obtenez l'entier minimum
int minInt = 1 << 31;
int minInt = 1 << -1;
Obtenez le maximum long
long maxLong = ((long)1 << 127) - 1;
multiplié par 2
n << 1; // n*2
divisé par 2
n >> 1; // n/2
multiplié par la m-ème puissance de 2
n << m;
divisé par la m-ème puissance de 2
n >> m;
Vérifier le nombre impair
(n & 1) == 1;
échange deux valeurs
a ^= b;
b ^= a;
a ^= b;
Obtenir la valeur absolue
(n ^ (n >> 31)) - (n >> 31);
Obtenez le maximum de deux valeurs
b & ((a-b) >> 31) | a & (~(a-b) >> 31);
Obtenez le minimum de deux valeurs
a & ((a-b) >> 31) | b & (~(a-b) >> 31);
Vérifiez si les deux ont le même signe
(x ^ y) >= 0;
Calculer 2 ^ n
2 << (n-1);
si est factoriel de 2
n > 0 ? (n & (n - 1)) == 0 : false;
Modulo 2 ^ n contre m
m & (n - 1);
Obtenez la moyenne
(x + y) >> 1;
((x ^ y) >> 1) + (x & y);
Obtenez le m-ème bit de n (de bas en haut)
(n >> (m-1)) & 1;
Réglez le m-ème bit de n sur 0 (de bas en haut)
n & ~(1 << (m-1));
n + 1
-~n
n - 1
~-n
Obtenez le numéro de contraste
~n + 1;
(n ^ -1) + 1;
si (x == a) x = b; si (x == b) x = a;
x = a ^ b ^ x;
Il n'y en a que trois que j'ai jamais utilisés avec n'importe quelle fréquence:
Définissez un bit: a | = 1 << bit;
Effacer un peu: a & = ~ (1 << bit);
Vérifiez qu'un bit est défini: a & (1 << bit);
Questions de calcul: idées, algorithmes, code source, par Jorg Arndt (PDF) . Ce livre contient des tonnes de choses, je l'ai trouvé via un lien à http://www.hackersdelight.org/
Moyenne sans débordement
Une routine pour le calcul de la moyenne (x + y)/2 de deux arguments x et y est
static inline ulong average(ulong x, ulong y) // Return floor( (x+y)/2 ) // Use: x+y == ((x&y)<<1) + (x^y) // that is: sum == carries + sum_without_carries { return (x & y) + ((x ^ y) >> 1); }
Vous pouvez compresser des données, par exemple une collection d'entiers:
J'ai utilisé des opérateurs au niveau du bit pour implémenter efficacement les calculs de distance pour chaînes de bits . Dans mon application, les chaînes de bits ont été utilisées pour représenter des positions dans un espace discrétisé (un octree , si vous êtes intéressé, codé avec Ordre Morton ). Les calculs de distance étaient nécessaires pour savoir si les points de la grille se situaient dans un rayon particulier.
Compter les bits de jeu, trouver le bit de jeu le plus bas/le plus élevé, trouver le nième jeu de bits du haut/du bas et d'autres peut être utile, et cela vaut la peine de regarder le site piratage de bits .
Cela dit, ce genre de chose n'est pas important au quotidien. Utile pour avoir une bibliothèque, mais même dans ce cas, les utilisations les plus courantes sont indirectes (par exemple, en utilisant un conteneur de bits). De plus, dans l'idéal, il s'agirait de fonctions de bibliothèque standard - beaucoup d'entre elles sont mieux gérées en utilisant des instructions CPU spécialisées sur certaines plates-formes.
1) Diviser/Multiplier par une puissance de 2
foo >>= x;
(diviser par puissance de 2)
foo <<= x;
(multiplier par la puissance de 2)
2) Échange
x ^= y;
y = x ^ y;
x ^= y;
Alors que multiplier/diviser par décalage semble astucieux, la seule chose dont j'avais besoin de temps en temps était de compresser les booléens en bits. Pour cela, vous avez besoin ET/OU au niveau du bit, et probablement de décalage/inversion de bits.
Je voulais une fonction pour arrondir les nombres à la prochaine puissance la plus élevée de deux, alors j'ai visité le site Web Bit Twiddling qui a été mentionné plusieurs fois et j'ai trouvé ceci:
i--;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i++;
Je l'utilise sur un type size_t
. Cela ne fonctionnera probablement pas bien sur les types signés. Si vous êtes préoccupé par la portabilité vers des plates-formes de différents types, saupoudrez votre code avec les directives #if SIZE_MAX >= (number)
aux endroits appropriés.