web-dev-qa-db-fra.com

Quelles astuces de code opérateur au niveau du bit UTILES un développeur doit-il connaître?

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?

62
non sequitor

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.

42
Martin Beckett

Utilisation d'opérations au niveau du bit sur des chaînes (caractères)

Convertir la lettre en en minuscules:

  • OR par espace => (x | ' ')
  • Le résultat est toujours en minuscules même si la lettre est déjà en minuscules
  • par exemple. ('a' | ' ') => 'a'; ('A' | ' ') => 'a'

Convertir la lettre en en majuscules:

  • AND par souligné => (x & '_')
  • Le résultat est toujours en majuscule même si la lettre est déjà en majuscule
  • par exemple. ('a' & '_') => 'A'; ('A' & '_') => 'A'

Inverser casse de la lettre:

  • XOR par espace => (x ^ ' ')
  • par exemple. ('a' ^ ' ') => 'A'; ('A' ^ ' ') => 'a'

Lettre position dans l'alphabet:

  • AND par chr(31)/binary('11111')/(hex('1F') => (x & "\x1F")
  • Le résultat est compris entre 1 et 26, la casse n'est pas importante
  • par exemple. ('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 ^ '@')
  • par exemple. ('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 ^ '`')
  • par exemple. ('d' ^ '`') => 4; ('x' ^ '`') => 25

Remarque: utiliser autre chose que les lettres anglaises produira des résultats inutiles

134
CSᵠ

  • Opérations au niveau du bit sur des entiers (int)

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;
57
Mohasin Ali

Il n'y en a que trois que j'ai jamais utilisés avec n'importe quelle fréquence:

  1. Définissez un bit: a | = 1 << bit;

  2. Effacer un peu: a & = ~ (1 << bit);

  3. Vérifiez qu'un bit est défini: a & (1 << bit);

13
Scott

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);
}
6
u0b34a0f6ae

Vous pouvez compresser des données, par exemple une collection d'entiers:

3
ChrisW

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.

2
ire_and_curses

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.

2
Steve314

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;
2
Taylor Leese

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.

1
sbi

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.

1
Chris Lutz