Cas d'utilisation réels d'opérateurs au niveau du bit [fermé]


224

Quels sont les cas d'utilisation réels des opérateurs binaires suivants?

  • ET
  • XOR
  • NE PAS
  • OU
  • Décalage gauche / droite

1
Je me souviens quand j'ai entendu parler d'eux pour la première fois, il semblait qu'ils n'étaient utilisés que pour le bas niveau c ... mais depuis lors, ils sont entrés par boîte à outils et je les utilise souvent, y compris lors de la programmation "de haut niveau". Ils sont juste comme + et * pour moi maintenant.
Oak

2
@Anon.: Dans mon esprit, le monde réel était censé signifier autre chose qu'une programmation de bas niveau qui est l'utilisation la plus évidente des opérateurs au niveau du bit.
Olivier Lalonde



Peut également utiliser XOR binaire pour trouver un nombre manquant dans une permutation: martinkysel.com/codility-permmissingelem-solution
Janac Meena

Réponses:


216
  • Champs de bits (drapeaux)
    Ils sont le moyen le plus efficace de représenter quelque chose dont l'état est défini par plusieurs propriétés "oui ou non". Les listes de contrôle d'accès sont un bon exemple; si vous avez disons 4 autorisations discrètes (lecture, écriture, exécution, changement de politique), il est préférable de le stocker dans 1 octet plutôt que de le gaspiller 4. Ceux-ci peuvent être mappés à des types d'énumération dans de nombreuses langues pour plus de commodité.

  • La communication sur les ports / sockets
    implique toujours des sommes de contrôle, la parité, des bits d'arrêt, des algorithmes de contrôle de flux, etc., qui dépendent généralement des valeurs logiques des octets individuels par opposition aux valeurs numériques, car le support peut uniquement être capable de transmettre un bit à un temps.

  • Compression, chiffrement
    Les deux dépendent fortement des algorithmes au niveau du bit. Regardez l' algorithme de dégonflage pour un exemple - tout est en bits, pas en octets.

  • Machines à états finis
    Je parle principalement du type de matériel embarqué, même si elles se trouvent également dans les logiciels. Ceux - ci sont combinatoires dans la nature - ils pourraient littéralement être obtenir « compilé » vers le bas à un tas de portes logiques, donc ils doivent être exprimés en AND, OR, NOT, etc.

  • Graphiques Il n'y a guère assez d'espace ici pour entrer dans tous les domaines où ces opérateurs sont utilisés dans la programmation graphique. XOR(ou ^) est particulièrement intéressant ici car appliquer la même entrée une deuxième fois annulera la première. Les anciennes interfaces graphiques s'en servaient pour la mise en évidence de la sélection et d'autres superpositions, afin d'éliminer le besoin de redessiner coûteux. Ils sont toujours utiles dans les protocoles graphiques lents (c'est-à-dire le bureau à distance).

Ce ne sont que les premiers exemples que j'ai trouvés - ce n'est pas une liste exhaustive.


Bonjour @Aaronaught, Vous avez vraiment partagé une très bonne connaissance avec nous. Je souhaite en savoir plus sur les cas réels de Bitwise Operator. Pourriez-vous partager votre référence avec nous, serait vraiment utile d'en savoir plus.
Heena Hussain

Les opérations au niveau du bit sont-elles utiles pour les calculs vectorisables?
Aaron Franke

47

Est-ce étrange?

(value & 0x1) > 0

Est-il divisible par deux (pair)?

(value & 0x1) == 0

3
En fonction de la valeur de votre langue, 0x1> 0 peut être analysé en tant que valeur & (0x1> 0)
leeeroy

3
@leeeroy - C'est vrai. Ajout de quelques parens.
Seth

Les optimiseurs modernes convertissent automatiquement les expressions telles que (valeur% 2)! = 0 en expressions ci-dessus. godbolt.org/z/mYEBH4
Ferrarezi

26

Voici quelques idiomes courants traitant des drapeaux stockés sous forme de bits individuels.

enum CDRIndicators {
  Local = 1 << 0,
  External = 1 << 1,
  CallerIDMissing = 1 << 2,
  Chargeable = 1 << 3
};

unsigned int flags = 0;

Réglez le drapeau facturable:

flags |= Chargeable;

Effacer l'indicateur CallerIDMissing:

flags &= ~CallerIDMissing;

Testez si CallerIDMissing et Chargeable sont définis:

if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {

}

25

J'ai utilisé des opérations au niveau du bit dans la mise en œuvre d'un modèle de sécurité pour un CMS. Il y avait des pages auxquelles les utilisateurs pouvaient accéder s'ils faisaient partie des groupes appropriés. Un utilisateur peut être dans plusieurs groupes, nous avons donc dû vérifier s'il y avait une intersection entre les groupes d'utilisateurs et les groupes de pages. Nous avons donc attribué à chaque groupe un identifiant unique de puissance de 2, par exemple:

Group A = 1 --> 00000001
Group B = 2 --> 00000010
Group C = 3 --> 00000100

Nous OU ensemble ces valeurs, et stockons la valeur (comme un seul entier) avec la page. Par exemple, si une page est accessible aux groupes A et B, nous stockons la valeur 3 (qui en binaire est 00000011) comme contrôle d'accès aux pages. De la même manière, nous stockons une valeur d'identificateurs de groupe OR avec un utilisateur pour représenter les groupes dans lesquels ils se trouvent.

Donc, pour vérifier si un utilisateur donné peut accéder à une page donnée, il vous suffit de ET ensemble les valeurs et de vérifier si la valeur est non nulle. C'est très rapide car cette vérification est implémentée en une seule instruction, sans boucle, sans aller-retour dans la base de données.


24

La programmation de bas niveau est un bon exemple. Vous pouvez, par exemple, avoir besoin d'écrire un bit spécifique dans un registre mappé en mémoire pour faire en sorte qu'un matériel fasse ce que vous voulez:

volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t          value;
uint32_t          set_bit   = 0x00010000;
uint32_t          clear_bit = 0x00001000;

value = *register;            // get current value from the register
value = value & ~clear_bit;   // clear a bit
value = value | set_bit;      // set a bit
*register = value;            // write it back to the register

De plus, htonl()et htons()sont implémentés à l'aide des opérateurs &et |(sur les machines dont l' endianité (ordre des octets) ne correspond pas à l'ordre du réseau):

#define htons(a) ((((a) & 0xff00) >> 8) | \
                  (((a) & 0x00ff) << 8))

#define htonl(a) ((((a) & 0xff000000) >> 24) | \
                  (((a) & 0x00ff0000) >>  8) | \
                  (((a) & 0x0000ff00) <<  8) | \
                  (((a) & 0x000000ff) << 24))

7
Tout le monde ne parle pas à la machine. Quel est votre deuxième exemple?
ChaosPandion

7
htons()et htonl()sont des fonctions POSIX pour échanger un shortou un longde l' hendianité de l'hôte ( ) à l' nordre des octets du réseau ( ).
Carl Norum

Vous pouvez utiliser une méthode similaire pour effectuer une inversion de bits dans les opérations O (logN).
Mike DeSimone

lol quand j'ai vu cela pour la première fois, je pensais que c'était l'assemblage!
0x499602D2

N'est-ce pas htonl()pour une intvaleur 32 bits ? longsignifie 64 bits dans de nombreuses langues.
Aaron Franke

21

Je les utilise pour obtenir des valeurs RVB (A) à partir de valeurs de couleurs emballées, par exemple.


Et ça le fait très vite!
Callum Rogers

En C #, c'est l'un de ces cas où c'est vraiment la meilleure solution, pour la lisibilité et la vitesse.
CaptainCasey

4
Sur ma machine, (a & b) >> cest plus de 5 fois plus rapide que a % d / e(les deux façons d'extraire une seule valeur de couleur d'un int représentant ARGB). Respectivement, 6,7 s et 35,2 s pour 1 milliard d'itérations.
Benji XVI

@BenjiXVI C # a des optimisations de compilateur pour cela. La raison pour laquelle vous observez une différence de vitesse est que, en C #, ce %n'est pas l'opérateur Module, c'est l'opérateur Restant. Ils sont équivalents pour les valeurs positives mais diffèrent par les valeurs négatives. Si vous fournissez les restrictions appropriées (en passant un uintau lieu de intpar exemple), les deux exemples doivent avoir la même vitesse.
Aaron Franke

désolé, je sais que ça fait longtemps. Pouvez-vous s'il vous plaît montrer un exemple de la façon de les utiliser pour obtenir chaque valeur RVB unique?
Jinx

14

Quand j'ai un tas de drapeaux booléens, j'aime les stocker tous dans un int.

Je les fais sortir en utilisant ET au niveau du bit. Par exemple:

int flags;
if (flags & 0x10) {
  // Turn this feature on.
}

if (flags & 0x08) {
  // Turn a second feature on.
}

etc.


23
J'espère que ce sont en fait des constantes dans votre vrai code et non des nombres magiques :)
Earlz

1
Un exemple d'utilisation de drapeaux booléens dans le monde non de bas niveau consiste à faire des choses avec diverses plates-formes GUI. Par exemple, vous pouvez utiliser my_button.Style | = STYLE_DISABLED pour le désactiver.
MauriceL

1
Je sais que ce sujet est indépendant du langage, mais C fournit un moyen facile de le faire avec des champs binaires afin que vous puissiez utiliser des choses comme if (flags.feature_one_is_one) { // turn on feature }. C'est dans la norme ANSI C, donc la portabilité ne devrait pas être un problème.
polandeer

ce serait bien d'avoir une explication de ce que fait cet extrait de code, pourquoi les drapeaux ne sont pas initialisés, que voulez-vous dire par "les stocker tous dans un int", quelle est la notation utilisée ...
Angelo Oparah

12

& = ET:
Masque des bits spécifiques.
Vous définissez les bits spécifiques qui doivent être affichés ou non affichés. 0x0 & x effacera tous les bits d'un octet tandis que 0xFF ne changera pas x. 0x0F affichera les bits dans le quartet inférieur.

Conversion:
pour convertir des variables plus courtes en variables plus longues avec une identité binaire, il est nécessaire d'ajuster les bits car -1 dans un entier est 0xFFFFFFFF tandis que -1 dans un long est 0xFFFFFFFFFFFFFFFF. Pour préserver l'identité, vous appliquez un masque après la conversion.

| = OU
Définissez les bits. Les bits seront définis indépendamment s'ils sont déjà définis. De nombreuses infrastructures de données (champs binaires) ont des indicateurs comme IS_HSET = 0, IS_VSET = 1 qui peuvent être définis indépendamment. Pour définir les indicateurs, vous appliquez IS_HSET | IS_VSET (en C et en assemblage, c'est très pratique à lire)

^ = XOR
Recherche des bits identiques ou différents.

~ = PAS
Flip bits.

On peut montrer que toutes les opérations binaires locales possibles peuvent être mises en œuvre par ces opérations. Donc, si vous le souhaitez, vous pouvez implémenter une instruction ADD uniquement par des opérations binaires.

Quelques merveilleux hacks:

http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html


Ce qui suit est un lien qui donne d'excellents exemples d'utilisation d'opérateurs au niveau du bit dans AS3 pour des opérations mathématiques ultra rapides (mais il pourrait probablement être appliqué à la plupart des langues): lab.polygonal.de/2007/05/10/bitwise-gems-fast- nombres entiers
fortement impliqué

Je pense que "NON" devrait être = ~, non |=, ce qui est OU.
Mike DeSimone

Pour & = AND- Pourquoi voudrais-je effacer tous les bits, pourquoi voudrais-je vouloir obtenir une version non modifiée de l'octet, et que dois-je faire avec le quartet inférieur?
confused00

1
@ confused00 à droite, la manière la plus rapide / simple d'annuler un résultat est de xorlui-même. Je peux penser à plusieurs raisons pour lesquelles vous voudrez peut-être extraire le quartet inférieur. Surtout si ce quartet inférieur fait partie d'une structure de données et que vous souhaitez l'utiliser comme masque ou ORavec une autre structure.
James M. Lay

11

Le chiffrement est toutes les opérations au niveau du bit.


4
Vraiment? Les implémentations de chiffrement sont susceptibles d'utiliser des opérations au niveau du bit, mais les algorithmes de chiffrement sont généralement décrits en termes numériques et non en termes de représentations binaires.
Constantin

1
Alors, que faites-vous avec des algorithmes autres que de les implémenter? Je suis curieux.
récursif le

2
@Constantin: Voir, par exemple, la description de la mise en œuvre de DES: ( en.wikipedia.org/wiki/…
Wayne Conrad

1
@recursive, si vous posez des questions sur moi personnellement - je ne conçois ni ne mets en œuvre d'algorithmes cryptographiques. Mais les gens font beaucoup de choses, comme les analyser pour les faiblesses théoriques.
Constantin

@Constantin: jetez un œil à ceci, ce n'est qu'un exemple parmi tant d'autres sur la façon dont (une partie des) algorithmes cryptographiques sont généralement décrits: en.wikipedia.org/wiki/Substitution_box
SyntaxT3rr0r

9

Vous pouvez les utiliser comme un moyen rapide et sale de hacher des données.

int a = 1230123;
int b = 1234555;
int c = 5865683;
int hash = a ^ b ^ c;

8

Je viens d'utiliser bitwise-XOR ( ^) il y a environ trois minutes pour calculer une somme de contrôle pour la communication série avec un automate ...


7

Bitwise & est utilisé pour masquer / extraire une certaine partie d'un octet.

Variable de 1 octet

 01110010
&00001111 Bitmask of 0x0F to find out the lower nibble
 --------
 00000010

En particulier, l'opérateur de décalage (<< >>) est souvent utilisé pour les calculs.


6

Ceci est un exemple pour lire les couleurs d'une image bitmap au format octet

byte imagePixel = 0xCCDDEE; /* Image in RRGGBB format R=Red, G=Green, B=Blue */

//To only have red
byte redColour = imagePixel & 0xFF0000; /*Bitmasking with AND operator */

//Now, we only want red colour
redColour = (redColour >> 24) & 0xFF;  /* This now returns a red colour between 0x00 and 0xFF.

J'espère que ces petits exemples vous aideront ...


5

Dans le monde abstrait de la langue moderne d'aujourd'hui, pas trop. L'entrée-sortie de fichier est une tâche facile qui me vient à l'esprit, bien qu'elle consiste à exercer des opérations au niveau du bit sur quelque chose déjà implémenté et n'implémente pas quelque chose qui utilise des opérations au niveau du bit. Néanmoins, à titre d'exemple simple, ce code illustre la suppression de l'attribut en lecture seule sur un fichier (afin qu'il puisse être utilisé avec un nouveau FileStream spécifiant FileMode.Create) en c #:

//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
    FileAttributes attributes = File.GetAttributes(targetName);

    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));

    File.Delete(targetName);
}

En ce qui concerne les implémentations personnalisées, voici un exemple récent: j'ai créé un "centre de messages" pour envoyer des messages sécurisés d'une installation de notre application distribuée à une autre. Fondamentalement, il est analogue au courrier électronique, avec Inbox, Outbox, Sent, etc., mais il a également une livraison garantie avec des accusés de lecture, il existe donc des sous-dossiers supplémentaires au-delà de "boîte de réception" et "envoyé". Ce que cela signifiait était une obligation pour moi de définir de manière générique ce qui est "dans la boîte de réception" ou ce qui est "dans le dossier envoyé". Du dossier envoyé, j'ai besoin de savoir ce qui est lu et ce qui n'est pas lu. De ce qui n'est pas lu, j'ai besoin de savoir ce qui est reçu et ce qui ne l'est pas. J'utilise ces informations pour créer une clause where dynamique qui filtre une source de données locale et affiche les informations appropriées.

Voici comment l'énumération est constituée:

    public enum MemoView :int
    {
        InboundMemos = 1,                   //     0000 0001
        InboundMemosForMyOrders = 3,        //     0000 0011
        SentMemosAll = 16,                  //     0001 0000
        SentMemosNotReceived = 48,          //     0011
        SentMemosReceivedNotRead = 80,      //     0101
        SentMemosRead = 144,                //     1001
        Outbox = 272,                       //0001 0001 0000
        OutBoxErrors = 784                  //0011 0001 0000
    }

Voyez-vous ce que cela fait? En anding (&) avec la valeur d'énumération "Inbox", InboundMemos, je sais que InboundMemosForMyOrders est dans la boîte de réception.

Voici une version réduite de la méthode qui crée et renvoie le filtre qui définit une vue pour le dossier actuellement sélectionné:

    private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
    {
        string filter = string.Empty;
        if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
        {
            filter = "<inbox filter conditions>";

            if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
            {
                filter += "<my memo filter conditions>";
            }
        }
        else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
        {
            //all sent items have originating system = to local
            filter = "<memos leaving current system>";

            if((view & MemoView.Outbox) == MemoView.Outbox)
            {
                ...
            }
            else
            {
                //sent sub folders
                filter += "<all sent items>";

                if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
                {
                    if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
                    {
                        filter += "<not received and not read conditions>";
                    }
                    else
                        filter += "<received and not read conditions>";
                }
            }
        }

        return filter;
    }

Extrêmement simple, mais une implémentation soignée à un niveau d'abstraction qui ne nécessite généralement pas d'opérations au niveau du bit.


4

L'encodage Base64 en est un exemple. Le codage Base64 est utilisé pour représenter les données binaires sous forme de caractères imprimables pour l'envoi via des systèmes de messagerie (et à d'autres fins). Le codage Base64 convertit une série d'octets 8 bits en index de recherche de caractères 6 bits. Les opérations sur les bits, le décalage et le «ou», le «pas» sont très utiles pour implémenter les opérations sur les bits nécessaires au codage et au décodage Base64.

Bien sûr, ce n'est qu'un des innombrables exemples.



4

Les opérations au niveau du bit sont généralement plus rapides que la multiplication / division. Donc, si vous devez multiplier une variable x par 9, vous ferez ce x<<3 + xqui serait quelques cycles plus rapide que x*9. Si ce code se trouve dans un ISR, vous économiserez du temps de réponse.

De même, si vous souhaitez utiliser un tableau comme file d'attente circulaire, il serait plus rapide (et plus élégant) de gérer les contrôles de bouclage avec des opérations au niveau du bit. (la taille de votre baie doit être une puissance de 2). Par exemple:, vous pouvez utiliser à la tail = ((tail & MASK) + 1)place de tail = ((tail +1) < size) ? tail+1 : 0, si vous souhaitez insérer / supprimer.

De plus, si vous souhaitez qu'un indicateur d'erreur contienne plusieurs codes d'erreur, chaque bit peut contenir une valeur distincte. Vous pouvez ET avec chaque code d'erreur individuel comme vérification. Ceci est utilisé dans les codes d'erreur Unix.

Un bitmap à n bits peut également être une structure de données vraiment cool et compacte. Si vous souhaitez allouer un pool de ressources de taille n, nous pouvons utiliser un n-bits pour représenter l'état actuel.


3

Personne ne semble avoir mentionné les mathématiques à virgule fixe.

(Ouais, je suis vieux, ok?)


3

Un nombre est-il xune puissance de 2? (Utile par exemple dans les algorithmes où un compteur est incrémenté et où une action ne doit être effectuée que le nombre de fois logarithmique)

(x & (x - 1)) == 0

Quel est le bit le plus élevé d'un entier x? (Ceci peut par exemple être utilisé pour trouver la puissance minimale de 2 supérieure à x)

x |= (x >>  1);
x |= (x >>  2);
x |= (x >>  4);
x |= (x >>  8);
x |= (x >> 16);
return x - (x >>> 1); // ">>>" is unsigned right shift

Quel est le 1bit le plus bas d'un entier x? (Aide à trouver le nombre de fois divisible par 2.)

x & -x

le décalage à droite non signé se fait en C en convertissant le LHS en type non signé. Votre dernière formule ne trouve pas le bit [set] le plus bas, elle vérifie si X est une puissance de 2. Pour trouver le bit le plus bas, faites x & -x.
Potatoswatter

Hmm, tu as raison, en quelque sorte j'ai remplacé x & -x par le premier extrait, thx pour le montage
Dimitris Andreou

3

Les opérateurs au niveau du bit sont utiles pour boucler des tableaux dont la longueur est une puissance de 2. Comme beaucoup de personnes l'ont mentionné, les opérateurs au niveau du bit sont extrêmement utiles et sont utilisés dans les indicateurs , les graphiques , les réseaux , le cryptage . Non seulement cela, mais ils sont extrêmement rapides. Mon utilisation préférée personnelle est de boucler un tableau sans conditions . Supposons que vous ayez un tableau basé sur un indice zéro (par exemple, l'indice du premier élément est 0) et que vous ayez besoin de le boucler indéfiniment. Par indéfiniment, je veux dire passer du premier élément au dernier et revenir au premier. Une façon de mettre en œuvre ceci est:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    if (i >= arr.length) 
        i = 0;
}

C'est l'approche la plus simple, si vous souhaitez éviter l' instruction if , vous pouvez utiliser l' approche module comme ceci:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    i = i % arr.length;
}

L'inconvénient de ces deux méthodes est que l'opérateur de module est coûteux, car il recherche un reste après la division entière. Et la première méthode exécute une instruction if à chaque itération. Avec l'opérateur au niveau du bit, cependant, si la longueur de votre tableau est une puissance de 2, vous pouvez facilement générer une séquence comme 0 .. length - 1en utilisant l' &opérateur (au niveau du bit et) comme tel i & length. Donc, sachant cela, le code d'en haut devient

int[] arr = new int[8];
int i = 0;
while (true){
    print(arr[i]);
    i = i + 1;
    i = i & (arr.length - 1);
}

Voici comment cela fonctionne. Au format binaire , chaque nombre dont la puissance de 2 est soustraite de 1 est exprimé uniquement avec des nombres. Par exemple, 3 en binaire est 11, 7 est 111, 15 est 1111et ainsi de suite, vous avez l'idée. Maintenant, que se passe-t-il si vous &n'importe quel nombre contre un nombre composé uniquement de ceux en binaire? Disons que nous faisons ceci:

num & 7;

Si numest plus petit ou égal à 7, le résultat sera numparce que chaque bit &avec 1 est lui-même. Si numest plus grand que 7, pendant l' &opération, l'ordinateur considérera les zéros de tête de 7 qui, bien sûr, resteront comme des zéros après l' &opération, seule la partie arrière restera. Comme en 9 & 7binaire ça ressemblera

1001 & 0111

le résultat sera 0001 qui est 1 en décimal et adresse le deuxième élément du tableau.


Votre remarque à mi-chemin du texte si la longueur de votre tableau est une puissance de 2 doit être mise dans la première phrase. C'est une limitation très sérieuse à l'utilisation de cette astuce. Personnellement, je ne mettrais pas cela en œuvre de toute façon, le code est plus difficile à comprendre que les approches if ou mod .
Jan Doggen

@JanDoggen Vous avez raison, je vais le mettre dans la première phrase. En ce qui concerne le tableau étant une puissance de deux, d'après mon expérience, il y a eu plus de quelques fois où cela a fonctionné. Probablement parce que c'était lié au réseau et aux graphiques.
user3552161

1
Le but de cet article était de montrer que les opérateurs au niveau du bit sont utiles pour générer des séquences de nombres, 0, 1, 2, 3, 0, 1, 2 ... la séquence n'était que la première qui me venait à l'esprit.
user3552161

2

Je les utilise pour les options de sélection multiple, de cette façon je ne stocke qu'une seule valeur au lieu de 10 ou plus


2

il peut également être pratique dans un modèle relationnel sql, disons que vous avez les tableaux suivants: BlogEntry, BlogCategory

traditionnellement, vous pouvez créer une relation nn entre eux à l'aide d'une table BlogEntryCategory ou lorsqu'il n'y a pas beaucoup d'enregistrements BlogCategory, vous pouvez utiliser une valeur dans BlogEntry pour créer un lien vers plusieurs enregistrements BlogCategory comme vous le feriez avec des énumérations marquées, dans la plupart des SGBDR, il existe également un opérateur très rapide pour sélectionner sur cette colonne "marquée" ...


2

Lorsque vous souhaitez uniquement modifier certains bits des sorties d'un microcontrôleur, mais que le registre dans lequel écrire est un octet, vous faites quelque chose comme ceci (pseudocode):

char newOut = OutRegister & 0b00011111 //clear 3 msb's
newOut = newOut | 0b10100000 //write '101' to the 3 msb's
OutRegister = newOut //Update Outputs

Bien sûr, de nombreux microcontrôleurs vous permettent de changer chaque bit individuellement ...


quelle langue est-ce censé être?
Carson Myers

@Carson: Pas de langue, c'est du pseudocode. Quand j'ai fait ça il y a quelques années, c'était Assembly, mais je suppose que c'est facile de le faire en C. Merci pour la tête, je vais mettre à jour pour que ce soit plus clair
Emilio M Bumachar

J'ai édité la réponse pour changer les commentaires afin que la mise en évidence ne soit pas si fausse. Et je vois, je pensais que c'était peut-être C mais vous avez utilisé la notation 0b ... que je souhaiterais être disponible en C.
Carson Myers

2

Si jamais vous voulez calculer votre nombre mod (%) une certaine puissance de 2, vous pouvez utiliser yourNumber & 2^N-1, qui dans ce cas est le même que yourNumber % 2^N.

number % 16 = number & 15;
number % 128 = number & 127;

C'est probablement seulement utile étant une alternative au fonctionnement du module avec un très gros dividende qui est 2 ^ N ... Mais même alors, son augmentation de vitesse par rapport au fonctionnement du module est négligeable dans mon test sur .NET 2.0. Je soupçonne que les compilateurs modernes effectuent déjà des optimisations comme celle-ci. Quelqu'un en sait-il plus?


Les compilateurs utilisent cette optimisation ... mais si vous ne connaissiez pas l'optimisation, vous pourriez ne pas choisir un diviseur qui a une puissance exacte de 2.
Ben Voigt

Ça dépend de la situation. En C #, cela produit en fait des résultats différents, tout comme %l'opération Remainder, ils traitent les négatifs différemment. Cependant, si vous passez uintà %, le compilateur C # produira réellement du code machine en utilisant AND au niveau du bit lorsque le deuxième argument est une puissance pré-connue de deux.
Aaron Franke

1

Je les ai vus utilisés dans des systèmes de contrôle d'accès basés sur les rôles.



1

Ils sont principalement utilisés pour les opérations au niveau du bit (surprise). Voici quelques exemples concrets trouvés dans la base de code PHP.

Encodage de caractère:

if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_KOI8R) {

Structures de données:

ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;

Pilotes de base de données:

dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);

Implémentation du compilateur:

opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;

1

Chaque fois que j'ai commencé la programmation en C, j'ai compris les tables de vérité et tout ça, mais tout n'a pas cliqué sur la façon de l'utiliser réellement jusqu'à ce que je lise cet article http://www.gamedev.net/reference/articles/article1563.asp (qui donne des exemples concrets)


1
Non, ce n'est pas pareil. En C, si x == 1et y == 2, alors x || ys'évalue à 1 et x | ys'évalue à 0. Je ne vois pas non plus pourquoi x^trueest supérieur à !xd'aucune façon. C'est plus typant, moins idiomatique, et si ce xn'est pas le cas, boolce n'est pas fiable.
David Thornley

oh attends .. oui, c'est idiot de ma part .. Je n'arrive pas à penser correctement aujourd'hui.
Earlz

x | y évalue à 3 (edit: nvm, je vois que vous parliez de quelque chose de retravaillé!)
Pod

1
@DavidThornley: Un cas où x^trueest supérieur à !xest some->complicated().member->lookup ^= true; Il n'y a pas de versions à affectation composée d'opérateurs unaires.
Ben Voigt

1

Je ne pense pas que cela compte comme bit à bit, mais le tableau de ruby ​​définit les opérations de set via les opérateurs bit à bit entiers normaux. Alors [1,2,4] & [1,2,3] # => [1,2]. De même pour a ^ b #=> set differenceet a | b #=> union.


1

La solution linéaire Tower Of Hanoi utilise des opérations au niveau du bit pour résoudre le problème.

public static void linear(char start, char temp, char end, int discs)
{
    int from,to;
    for (int i = 1; i < (1 << discs); i++) {
        from = (i & i-1) % 3;
        to = ((i | i-1) + 1) % 3;
        System.out.println(from+" => "+to);
    }
}

L'explication de cette solution se trouve ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.