mozilla
Vos résultats de recherche

    Opérateurs binaires

    Les opérateurs binaires traitent leurs opérandes comme des séquences de 32 bits (des zéros et des uns), plutôt que comme des nombres décimaux, hexadécimaux ou octaux. Par exemple, le nombre décimal neuf a une représentation binaire de 1001. Les opérateurs binaires traitent de telles représentations binaires, mais renvoient des valeurs numériques JavaScript standards.

    Le tableau qui suit résume les opérateurs binaires de JavaScript :

    Opérateur Utilisation Description
    ET binaire a & b

    Renvoie un 1 pour chaque position de bit pour laquelle les bits correspondants des deux opérandes sont des 1.

    OU binaire a | b Renvoie un 1 pour chaque position de bit pour laquelle le bit correspondant d'au moins un des deux opérandes est un 1 .
    OU exclusif binaire (XOR) a ^ b Renvoie un 1 pour chaque position de bit pour laquelle le bit correspondant d'un seul des deux opérandes est un 1.
    NON binaire ~ a Inverse les bits de son opérande.
    Décalage à gauche a << b Décale a en représentation binaire de b bits vers la gauche, en introduisant des zéros par la droite.
    Décalage à droite avec propagation du signe a >> b Décale a en représentation binaire de b bits vers la droite, en rejetant les bits à droite.
    Décalage à droite avec introduction de zéros a >>> b Décale a en représentation binaire de b bits vers la droite, en rejetant les bits à droite et en introduisant des zéros par la gauche.

    Entiers sur 32 bits signés

    Les opérandes de tous les opérateurs binaires sont convertis en entiers signés sur 32 bits  en ordre big-endian et en format de complément à deux. L'ordre big-endian signifie que le bit le plus significatif (la position du bit qui a la plus grande valeur) est le bit le plus à gauche si les 32 bits sont disposés sur une ligne horizontale. Le format de complément à deux signifie que la contrepartie négative d'un nombre (par exemple 5 pour -5) est l'inversion de tous les bits du nombre (NON binaire du nombre, c'est-à-dire son complément à un) plus un. Par exemple, la représentation suivante encode l'entier 314 (base 10) :

    00000000000000000000000100111010
    

    La représentation suivante encode ~314, c'est-à-dire le complément à un de 314 :

    11111111111111111111111011000101
    

    Finalement, la représentation suivante encode -314, c'est-à-dire le complément à deux de 314 :

    11111111111111111111111011000110
    

    Le complément à deux garantit que le bit le plus à gauche soit 0 lorsque le nombre est positif, et 1 lorsque le nombre est négatif. C'est pourquoi on l'appelle le bit de signe .

    Le nombre 0 est l'entier constitué intégralement de bits à 0 .

    0 (base 10) = 00000000000000000000000000000000 (base 2)

    Le nombre -1 est l'entier constitué intégralement de bits à 1 .

    -1 (base 10) = 11111111111111111111111111111111 (base 2)

    Le nombre -2147483648 (qui correspond à -0x80000000 en notation hexadécimale) est l'entier uniquement composé de 0, à l'exception du premier bit (le plus à gauche) qui vaut 1.

    -2147483648 (base 10) = 10000000000000000000000000000000 (base 2)

    Le nombre 2147483647 (qui correspond à 0x7fffffff en notation hexadécimale) est l'entier uniquement composé de 1, à l'exception du premier bit (le plus à gauche) qui vaut 0.

    2147483647 (base 10) = 01111111111111111111111111111111 (base 2)

    Les nombres -2147483648 et 2147483647 sont respectivement le nombre le plus petit et le plus grand qu'on peut représenter sur 32 bits (signés).

    Opérateurs logiques binaires

    Conceptuellement, les opérateurs logiques binaires fonctionnent de la manière suivante :

    • Les opérandes sont convertis en entiers 32 bits et sont exprimés sous la forme d'une série de bits (zéros et uns).
    • Chaque bit du premier opérande est combiné avec le bit correspondant du second opérande : le premier bit avec le premier bit, le second bit avec le second bit, et ainsi de suite.
    • L'opérateur est appliqué à chaque paire de bits, et le résultat est construit bit après bit.

    & (ET binaire)

    Effectue l'opération ET (AND) sur chaque paire de bits. a ET b donne 1 uniquement si à la fois a et b sont 1 . La table de vérité pour l'opération ET est :

    a b a ET b
    0 0 0
    0 1 0
    1 0 0
    1 1 1
         9 (base 10) = 00000000000000000000000000001001 (base 2)
        14 (base 10) = 00000000000000000000000000001110 (base 2)
                       --------------------------------
    14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)
    

    Utiliser le ET binaire avec n'importe quel nombre x et zéro donne zéro. Utiliser le ET binaire avec n'importe quel nombre x et -1 donne x.

    | (OU binaire)

    Effectue l'opération OU (OR) sur chaque paire de bits. a OU b donne 1 si a ou b vaut 1. La table de vérité pour l'opération OU est :

    a b a OU b
    0 0 0
    0 1 1
    1 0 1
    1 1 1
         9 (base 10) = 00000000000000000000000000001001 (base 2)
        14 (base 10) = 00000000000000000000000000001110 (base 2)
                       --------------------------------
    14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)
    

    Utiliser le OU binaire avec n'importe quel nombre x et 0 donne x. Utiliser le OU binaire avec n'importe quel nombre x et -1 donne -1.

    ^ (XOR binaire)

    Effectue l'opération XOR (OU exclusif) sur chaque paire de bits. a XOR b donne 1 si a et b sont différents. La table de vérité pour l'opération XOR est :

    a b a XOR b
    0 0 0
    0 1 1
    1 0 1
    1 1 0
         9 (base 10) = 00000000000000000000000000001001 (base 2)
        14 (base 10) = 00000000000000000000000000001110 (base 2)
                       --------------------------------
    14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)
    

    Utiliser le XOR binaire avec n'importe quel nombre x et 0 donne x. Utiliser le XOR binaire avec n'importe quel nombre x et -1 donne ~x.

    ~ (NON binaire)

    Effectue l'opération NON (NOT) sur chaque bit. NON a donne la valeur inversée (c'est-à-dire le complément à un) de a. La table de vérité de l'opération NON est :

    a NON a
    0 1
    1 0
     9 (base 10) = 00000000000000000000000000001001 (base 2)
                   --------------------------------
    ~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)
    

    Utiliser le NON binaire avec n'importe quel nombre x donne -(x + 1). Par exemple, ~5 donne -6.

    Voici un autre exemple avec indexOf :

    var str = 'ouaf';
    var carRecherché = 'a';
    
    // une autre méthode pour tester si (-1*str.indexOf('a') <= -1)
    if (~str.indexOf(carRecherché)) {
      // carRecherché est dans la chaîne
    } else {
      // carRecherché n'est pas dans la chaîne
    }
    
    // voici les valeurs renvoyées par (~str.indexOf(carRecherché))
    // o == -1
    // u == -2
    // a == -3
    // f == -4

    Opérateurs de décalage binaire

    Les opérateurs de décalage binaire (shift) prennent deux opérandes : le premier est une valeur à décaler et le second spécifie le nombre de positions de bits duquel le premier opérande doit glisser. La direction de l'opération de décalage est contrôlée par l'opérateur utilisé.

    Les opérateurs de décalage convertissent leurs opérandes en entiers 32 bits en ordre big-endian et renvoient un résultat du même type que l'opérande de gauche. L'opérande droit doit être inférieur à 32, sinon les cinq bits les plus faibles seront utilisés.

    << (décalage à gauche)

    Cet opérateur décale le premier opérande du nombre de bits spécifié vers la gauche. Les bits surnuméraires éjectés à gauche sont perdus. Des bits à zéro sont insérés par la droite.

    Par exemple, 9 << 2 donne 36 :

         9 (base 10) : 00000000000000000000000000001001 (base 2)
                       --------------------------------
    9 << 2 (base 10) : 00000000000000000000000000100100 (base 2) = 36 (base 10)
    

    Décaler un nombre x de y bits vers la gauche renverra x*2yx*2^y.

    >> (décalage à droite avec propagation du signe)

    Cet opérateur décale le premier opérande du nombre de bits spécifié vers la droite. Les bits surnuméraires éjectés à droite sont perdus. Des copies du bit le plus à gauche sont insérés par la gauche. Comme le bit le plus a gauche a la même valeur qu'avant l'opération, le bit de signe (celui qui est le plus à gauche) ne change pas. D'où ce qu'on appelle la « propagation du signe ».

    Par exemple, 9 >> 2 donne 2 :

         9 (base 10) : 00000000000000000000000000001001 (base 2)
                       --------------------------------
    9 >> 2 (base 10) : 00000000000000000000000000000010 (base 2) = 2 (base 10)
    

    De même, -9 >> 2 donne -3, parce que le signe est préservé :

         -9 (base 10) : 11111111111111111111111111110111 (base 2)
                        --------------------------------
    -9 >> 2 (base 10) : 11111111111111111111111111111101 (base 2) = -3 (base 10)
    

    >>> (décalage à droite avec insertion de zéros)

    Cet opérateur décale le premier opérande du nombre de bits spécifié vers la droite. Les bits surnuméraires éjectés à droite sont perdus. Des bits à zéro sont insérés par la gauche. Le bit de signe devient 0, donc le résultat est toujours positif.

    Pour les nombres non négatifs, le décalage à droite avec insertion de zéros et le décalage à droite avec propagation du signe donnent le même résultat. Par exemple, 9 >>> 2 donne 2, tout comme 9 >> 2 :

          9 (base 10) : 00000000000000000000000000001001 (base 2)
                        --------------------------------
    9 >>> 2 (base 10) : 00000000000000000000000000000010 (base 2) = 2 (base 10)
    

    Cependant, ce n'est pas le cas des nombres négatifs. Par exemple, -9 >>> 2 donne 1073741821, ce qui est différent de -9 >> 2 (qui donne -3) :

          -9 (base 10) : 11111111111111111111111111110111 (base 2)
                         --------------------------------
    -9 >>> 2 (base 10) : 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)
    

    Exemples

    Exemple : flags et bitmasks

    Les opérateurs logiques binaires sont souvent utilisés pour créer, manipuler et lire des séquences deflags , qui sont comme des variables binaires. On pourrait très bien utiliser des variables à la place de ces séquences binaires, mais des flags binaires prennent nettement moins de mémoire (par un facteur de 32).

    Supposons que l'on ait 4 flags :

    • flag A : nous avons une araignée
    • flag B : nous avons une belette
    • flag C : nous avons un chat
    • flag D : nous avons un dinosaure

    Ces flags sont représentés par une séquence de bits : DCBA. Lorsqu'un flag est positionné, il a une valeur de 1. Sinon, il a une valeur de 0. Supposons qu'une variable flags a la valeur binaire de 0101 :

    var flags = 0x5;   // 0101 en binaire
    

    Cette valeur indique :

    • le flag A est vrai (nous avons une araignée) ;
    • le flag B est faux (nous n'avons pas de belette) ;
    • le flag C est vrai (nous avons un chat) ;
    • le flag D est faux (nous n'avons pas de dinosaure).

    Comme les opérateurs binaires sont sur 32 bits, 0101 est en fait 00000000000000000000000000000101, mais les zéros qui précèdent peuvent être négligés étant donné qu'ils ne contiennent aucune information significative.

    Un bitmask est une séquence de bits qui peuvent manipuler et/ou lire des flags. Typiquement, un masque « primitif » pour chaque flag est défini :

    var FLAG_A = 0x1; // 0001
    var FLAG_B = 0x2; // 0010
    var FLAG_C = 0x4; // 0100
    var FLAG_D = 0x8; // 1000
    

    De nouveaux masques peuvent être créés à l'aide des opérateurs logiques binaires sur ces masques primitifs. Par exemple, le masque 1011 peut être créé avec une opération OU sur FLAG_A, FLAG_B et FLAG_D :

    var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011
    

    Des valeurs de flag particulières peuvent être extraites à l'aide d'une opération ET avec un bitmask, où chaque bit avec la valeur 1 va « extraire » le flag qui correspond. Le bitmask masque les flags dont on n'a pas besoin en effectuant l'opération ET avec des zéros (d'où le terme « bitmask »). Par exemple, le masque 0101 peut être utilisé pour voir si le flag C est positionné :

    // si l'on a un chat
    if (flags & FLAG_C) { // 0101 & 0100 => 0100 => true
       // faire quelque chose
    }
    

    Un masque avec plusieurs flags positionnés agit comme un « et/ou ». Par exemple, les deux instructions suivantes sont équivalentes :

    // si on a une belette ou si on a un chat
    if ((flags & FLAG_B) || (flags & FLAG_C)) { // (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true
       // faire quelque chose
    }
    
    // si on a une belette ou si on a un chat
    var mask = FLAG_B | FLAG_C; // 0010 | 0100 => 0110
    if (flags & mask) { // 0101 & 0110 => 0100 => true
       // faire quelque chose
    }
    

    Les flags peuvent être positionnés en utilisant l'opération OU avec un masque, où chaque bit de la valeur 1 définira le flag correspondant, si celui-ci n'est pas déjà positionné. Par exemple, le masque 1010 peut être utilisé pour positionner les flags C et D :

    // oui, on a un chat et un dinosaure
    var mask = FLAG_C | FLAG_D; // 0100 | 1000 => 1100
    flags |= mask;   // 0101 | 1100 => 1101
    

    Les flags peuvent être remis à zéro en utilisant l'opération ET avec un masque, où chaque bit avec la valeur 0 remettra à zéro le flag correspondant s'il ne l'est pas déjà. Ce masque peut être créé avec l'opération NOT sur les masques primitifs. Par exemple, le masque 1010 peut être utilisé pour remettre à zéro les flags A et C :

    // non, nous n'avons pas d'araignée ou de chat
    var mask = ~(FLAG_A | FLAG_C); // ~0101 => 1010
    flags &= mask;   // 1101 & 1010 => 1000
    

    Le masque aurait également pu être créé avec ~FLAG_A & ~FLAG_C (Loi de De Morgan) :

    // non, nous n'avons pas d'araignée ou de chat
    var mask = ~FLAG_A & ~FLAG_C;
    flags &= mask;   // 1101 & 1010 => 1000
    

    Les flags peuvent être inversés en utilisant l'opération XOR avec un masque, où chaque bit avec la valeur 1 inversera le flag correspondant. Par exemple, le masque 0110 peut être utilisé pour inverser les flags B et C :

    // si on n'avait pas de belette, on en a maintenant une.
    // si on en avait une, on ne l'a plus. Même chose pour les chats.
    var mask = FLAG_B | FLAG_C;
    flags = flags ^ mask;   // 1100 ^ 0110 => 1010
    

    Finalement, les flags peuvent être tous inversés avec l'opérateur NON :

    // entrée dans un univers parallèle...
    flags = ~flags;    // ~1010 => 0101
    

    Codes de conversion

    Pour convertir une String binaire en un Number (en base 10):

    var chaîneBinaire = "1011";
    var monNombre = parseInt(chaîneBinaire, 2);
    console.log(monNombre); // affiche 11 (1011 en base 2)
    

    Pour convertir un Number (en base 10) en une String binaire :

    var monNombre = 11;
    var chaîneBinaire = monNombre.toString(2);
    console.log(chaîneBinaire); // affiche 1011 (11 en base 10)
    

    Automatiser la création d'un masque

    Si vous devez créer plusieurs masques à partir de booléens, il est possible d'automatiser ce processus :

    function créerMasque () {
      var nMask = 0, nFlag = 0, nLen = arguments.length > 32 ? 32 : arguments.length;
      for (nFlag; nFlag < nLen; nMask |= arguments[nFlag] << nFlag++);
      return nMask;
    }
    var masque1 = créerMasque(true, true, false, true); // 11, i.e.: 1011
    var masque2 = créerMasque(false, false, true); // 4, i.e.: 0100
    var masque3 = créerMasque(true); // 1, i.e.: 0001
    // etc.
    
    console.log(masque1); // affiche 11, i.e.: 1011
    

    Algorithme réciproque : obtenir un tableau de booléen à partir d'un masque

    Si on souhaite créer un tableau de booléens à partir d'un masque, on pourra utiliser le code suivant :

    function tableauMasque (nMask) {
      // nMask doit être compris entre -2147483648 et 2147483647
      if (nMask > 0x7fffffff || nMask < -0x80000000) { 
        throw new TypeError("tableauMasque - intervalle de valeur dépassé"); 
      }
      for (var nShifted = nMask, aFromMask = []; nShifted; 
           aFromMask.push(Boolean(nShifted & 1)), nShifted >>>= 1);
      return aFromMask;
    }
    
    var tableau1 = tableauMasque(11);
    var tableau2 = tableauMasque(4);
    var tableau3 = tableauMasque(1);
    
    console.log("[" + tableau1.join(", ") + "]");
    // affiche "[true, true, false, true]", i.e.: 11, i.e.: 1011
    

    On peut ainsi utiliser les deux algorithmes :

    var test = 19; // un masque quelconque
    var résultat = créerMasque.apply(this, tableauMasque(test));
    
    console.log(résultat); // 19
    

    Pour l'exemple (car il existe la méthode Number.toString(2)), on peut également modifier l'algorithme précédent pour créer une chaîne à partir de la représentation binaire d'un nombre :

    function créerChaîneBinaire(nMask) {
      // nMask doit être compris entre -2147483648 et 2147483647
      for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
           nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
      return sMask;
    }
    
    var string1 = créerChaîneBinaire(11);
    var string2 = créerChaîneBinaire(4);
    var string3 = créerChaîneBinaire(1);
    
    console.log(string1);
    // affiche 00000000000000000000000000001011, i.e. 11
    

    Spécifications

    Spécification Statut Commentaires
    Première édition d'ECMAScript. Standard Définition initiale
    ECMAScript 5.1 (ECMA-262)
    La définition de 'Bitwise NOT operator' dans cette spécification.

    ECMAScript 5.1 (ECMA-262)
    La définition de 'Bitwise shift operators' dans cette spécification.

    ECMAScript 5.1 (ECMA-262)
    La définition de 'Binary bitwise operators' dans cette spécification.
    Standard  
    ECMAScript 6 (ECMA-262)
    La définition de 'Bitwise NOT operator' dans cette spécification.

    ECMAScript 6 (ECMA-262)
    La définition de 'Bitwise shift operators' dans cette spécification.

    ECMAScript 6 (ECMA-262)
    La définition de 'Binary bitwise operators' dans cette spécification.
    En cours de validation comme recommandation  

    Compatibilité des navigateurs

    Fonctionnalité Chrome Firefox (Gecko) Internet Explorer Opera Safari
    NON binaire (~) (Oui) (Oui) (Oui) (Oui) (Oui)
    ET binaire (&) (Oui) (Oui) (Oui) (Oui) (Oui)
    OU binaire (|) (Oui) (Oui) (Oui) (Oui) (Oui)
    OU exclusif (XOR) binaire (^) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à gauche (<<) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à droite (>>) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à droite non-signé (>>>) (Oui) (Oui) (Oui) (Oui) (Oui)
    Fonctionnalité Android Chrome pour Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
    NON binaire (~) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    ET binaire (&) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    OU binaire (|) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    OU exclusif (XOR) (^) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à gauche (<<) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à droite (>>) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)
    Décalage à droite non-signé (>>>) (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)

    Voir aussi

    Étiquettes et contributeurs liés au document

    Contributors to this page: Jeremie, teoli, BenoitL, Kyodev, SphinxKnight, thePivottt, titouandk
    Dernière mise à jour par : thePivottt,
    Masquer la barre latérale