web-dev-qa-db-fra.com

Changer un peu d'un entier

Nous avons un nombre entier

int x = 50;

en binaire, c'est

00110010

Comment puis-je changer le quatrième (4ème) bit par programmation?

28
pedram

Vous pouvez définir le quatrième bit d'un nombre en le faisant correspondre à une valeur nulle partout sauf dans le quatrième bit. Cela pourrait être fait comme

x |= (1u << 3);

De même, vous pouvez effacer le quatrième bit en effectuant une opération ET avec une valeur égale à un partout sauf dans le quatrième bit. Par exemple:

x &= ~(1u << 3);

Enfin, vous pouvez basculer le quatrième bit en XOR-IN avec une valeur nulle partout sauf dans le quatrième bit:

x ^= (1u << 3);

Pour voir pourquoi cela fonctionne, nous devons examiner deux choses:

  1. Quel est le comportement de l'opérateur << dans ce contexte?
  2. Quel est le comportement des opérateurs AND, OR et XOR ici?

Dans les trois extraits de code ci-dessus, nous avons utilisé l'opérateur << pour générer une valeur. L'opérateur << est l'opérateur décentré gauche au niveau du bit, qui prend une valeur puis décale tous ses bits d'un nombre de pas vers la gauche. Dans ton cas, j'ai utilisé

1u << 3

pour prendre la valeur 1 (qui a la représentation binaire 1) puis décaler tous ses bits sur trois points, en complétant les valeurs manquantes avec 0. Ceci crée la valeur binaire 1000, qui a un bit défini dans le quatrième bit.

Maintenant, pourquoi

x |= (1u << 3);

définir le quatrième bit du nombre? Cela concerne le fonctionnement de l'opérateur OR. L'opérateur |= ressemble à += ou *= à l'exception de OR au niveau du bit - cela équivaut à

x = x | (1u << 3);

Alors pourquoi OR-ing x avec la valeur binaire 1000 définit-il son quatrième bit? Cela a à voir avec la façon dont OR est défini:

0 | 0  == 0
0 | 1  == 1
1 | 0  == 1
1 | 1  == 1

Plus important encore, nous pouvons réécrire ceci de manière plus compacte

x | 0  == x
x | 1  == 1

Ceci est un fait extrêmement important, car cela signifie que l'opération OU-n'importe quel bit avec zéro ne change pas la valeur du bit, tandis que l'option OU-n'importe quel bit avec 1 définit toujours ce bit à un. Cela signifie que lorsque nous écrivons

x |= (1u << 3);

puisque (1u << 3) est une valeur nulle partout sauf dans le quatrième bit, le bitwise OR laisse tous les bits de x inchangés à l'exception du quatrième bit, qui est ensuite mis à un. Plus généralement, OU un nombre avec une valeur qui est une série de zéros et des uns conservera toutes les valeurs où les bits sont nuls et définira toutes les valeurs où les bits sont un.

Maintenant, regardons

x &= ~(1u << 3);

Ceci utilise l'opérateur de complément au niveau du bit ~, qui prend un nombre et retourne tous ses bits. Si nous supposons que les entiers sont deux octets (par souci de simplicité), cela signifie que le codage réel de (1u << 3) est

0000000000001000

Lorsque nous prenons le complément de ceci, nous obtenons le nombre

1111111111110111

Voyons maintenant ce qui se passe lorsque nous avons bitwise ET deux valeurs ensemble. L'opérateur AND a cette table de vérité intéressante:

0 & 0   == 0
0 & 1   == 0
1 & 0   == 0
1 & 1   == 1

Ou, plus compactement:

x & 0   == 0
x & 1   == x

Notez que cela signifie que si nous ET deux numéros ensemble, la valeur résultante sera telle que tous les bits AND-ed avec zéro sont mis à zéro, tandis que tous les autres bits sont conservés. Cela signifie que si nous ET avec

~(1u << 3)

nous etons avec

1111111111110111

Ainsi, dans notre tableau ci-dessus, cela signifie "conservez tous les bits, à l'exception du quatrième bit, tels quels, puis modifiez le quatrième bit pour qu'il soit à zéro".

Plus généralement, si vous souhaitez effacer un ensemble de bits, créez un nombre partout où vous souhaitez conserver les bits inchangés et à zéro là où vous souhaitez effacer les bits.

Enfin, voyons pourquoi

x ^= (1u << 3)

Retourne le quatrième bit du nombre. En effet, l'opérateur binaire XOR possède cette table de vérité:

0 ^ 0  == 0
0 ^ 1  == 1
1 ^ 0  == 1
1 ^ 1  == 0

Remarquerez que

x ^ 0  == 0
x ^ 1  == ~x

~x est l'opposé de x; c'est 0 pour 1 et 1 pour 0. Cela signifie que si nous XOR x avec la valeur (1u << 3), nous le vérifions avec XOR

0000000000001000

Cela signifie donc "conservez tous les bits sauf le quatrième bit tels quels, mais inversez le quatrième bit". Plus généralement, si vous souhaitez inverser un certain nombre de bits, XOR correspond à la valeur avec un nombre égal à zéro pour lequel vous souhaitez conserver les bits intacts et à un pour lequel vous souhaitez inverser ces bits.

J'espère que cela t'aides!

70
templatetypedef

Vous pouvez toujours utiliser std::bitset, ce qui facilite la modification des bits.

Vous pouvez également utiliser des manipulations de bits (en supposant que vous voulez dire que le quatrième bit compte pour un. Ne soustrayez pas 1 si vous voulez compter à partir de 0). Notez que j’utilise 1U uniquement pour garantir que toute l’opération se déroule sur des nombres non signés:

Pour définir: x |= (1U << (4 - 1));

Pour effacer: x &= ~(1U << (4 - 1));

Pour basculer: x ^= (1U << (4 - 1));

13
Mark B

Pour définir le quatrième bit, OR avec 00001000 (binaire).

Pour effacer le quatrième bit, AND avec 11110111 (binaire).

Pour basculer le quatrième bit, XOR avec 00001000 (binaire).

Exemples:

00110010 OR 00001000 = 00111010

00110010 et 11110111 = 00110010

00110010 XOR 00001000 = 00111010

7
Patrick87

Simple, puisque vous avez, ou quelle que soit votre valeur,

int x = 50;

Pour définir le 4ème bit (de droite) par programmation,

int y = x | 0x00000008;

Parce que, 0x préfixé avant un nombre signifie sa forme hexadécimale . Donc, 0x0 = 0000 en binaire, et 0x8=1000 en forme binaire . Cela explique la réponse.

2

Essayez une de ces fonctions en langage C pour changer n bit

char bitfield;

// start at 0th position

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}

void chang_n_bit(int n, int value)
{
    if(value)
        bitfield |= 1 << n;
    else
        bitfield &= ~0 ^ (1 << n);
}

char print_n_bit(int n)
{
    return (bitfield & (1 << n)) ? 1 : 0;
}
1
Vincet

Vous pouvez utiliser AND et OR binaires pour basculer le quatrième bit.

Pour définir le quatrième bit sur x, vous utiliseriez x |= 1<<3;, 1<<3 étant un décalage à gauche de 0b0001 de trois bits produisant 0b1000.

Pour effacer le quatrième bit sur x, vous utiliseriez x &= ~(1<<3);, un ET binaire compris entre 0b00110010 (x) et (effectivement) 0b11110111, en masquant tous les bits de x qui ne sont pas en position quatre et l'effacez.

0
Dustin Howett