web-dev-qa-db-fra.com

Valeur de contrôle du bit le moins significatif (LSB) et du bit le plus significatif (MSB) en C/C++

Je dois vérifier la valeur du bit le moins significatif (LSB) et du bit le plus significatif (MSB) d'un entier en C/C++. Comment je ferais ça?

21
delaccount992
//int value;
int LSB = value & 1;

Autre solution: {(théoriquement non portable, mais pratiquement - voir le commentaire de Steve))

//int value;
int LSB = value % 2;

Détails: La deuxième formule est plus simple. L'opérateur% est l'opérateur restant. Le numéro LSB d'un nombre est 1 si et seulement si c'est un nombre impair et 0 sinon. Nous vérifions donc le reste de la division par 2. La logique de la première formule est la suivante: le nombre 1 en binaire est le suivant:

0000...0001

Si vous utilisez un nombre binaire ET avec un nombre arbitraire, tous les bits du résultat seront 0 sauf le dernier, car 0 ET tout le reste est 0. Le dernier bit du résultat sera 1 si le dernier bit de votre nombre était 1 parce que 1 & 1 == 1 et 1 & 0 == 0

Ceci est un bon tutoriel pour les opérations au niveau des bits. 

HTH.

21
Armen Tsirunyan

Vous pouvez faire quelque chose comme ça:

#include <iostream>

int main(int argc, char **argv)
{
    int a = 3;
    std::cout << (a & 1) << std::endl;
    return 0;
}

De cette façon, vous AND votre variable avec le LSB, parce que

3: 011
1: 001

en représentation 3 bits. Donc, AND:

AND
-----
0  0  | 0
0  1  | 0
1  0  | 0
1  1  | 1

Vous serez en mesure de savoir si LSB est 1 ou non.

edit: find MSB.

Tout d’abord, lisez Endianess article pour vous mettre d’accord sur ce que MSB signifie. Dans les lignes suivantes, nous supposons traiter avec la notation big-endian.

Pour trouver la MSB, dans l'extrait suivant, nous allons appliquer un décalage à droite jusqu'à ce que la MSB devienne ANDed avec 1. Considérons le code suivant:

#include <iostream>
#include <limits.h>

int main(int argc, char **argv)
{
    unsigned int a = 128; // we want to find MSB of this 32-bit unsigned int
    int MSB = 0;   // this variable will represent the MSB we're looking for

    // sizeof(unsigned int) = 4 (in Bytes)
    // 1 Byte = 8 bits
    // So 4 Bytes are 4 * 8 = 32 bits
    // We have to perform a right shift 32 times to have the
    // MSB in the LSB position.
    for (int i = sizeof(unsigned int) * 8; i > 0; i--) {

        MSB = (a & 1); // in the last iteration this contains the MSB value

        a >>= 1; // perform the 1-bit right shift
    }

    // this prints out '0', because the 32-bit representation of
    // unsigned int 128 is:
    // 00000000000000000000000010000000
    std::cout << "MSB: " << MSB << std::endl; 

    return 0;
}

Si vous imprimez MSB en dehors du cycle, vous obtiendrez 0. Si vous modifiez la valeur de a:

unsigned int a = UINT_MAX; // found in <limits.h>

MSB sera 1, car sa représentation 32 bits est:

UINT_MAX: 11111111111111111111111111111111

Cependant, si vous faites la même chose avec un entier signé, les choses seront différentes.

#include <iostream>
#include <limits.h>

int main(int argc, char **argv)
{
    int a = -128; // we want to find MSB of this 32-bit unsigned int
    int MSB = 0; // this variable will represent the MSB we're looking for

    // sizeof(int) = 4 (in Bytes)
    // 1 Byte = 8 bits
    // So 4 Bytes are 4 * 8 = 32 bits
    // We have to perform a right shift 32 times to have the
    // MSB in the LSB position.
    for (int i = sizeof(int) * 8; i > 0; i--) {

        MSB = (a & 1); // in the last iteration this contains the MSB value

        a >>= 1; // perform the 1-bit right shift
    }

    // this prints out '1', because the 32-bit representation of
    // int -128 is:
    // 10000000000000000000000010000000
    std::cout << "MSB: " << MSB << std::endl; 

    return 0;
}

Comme je l'ai dit dans le commentaire ci-dessous, la MSB d'un entier positif est toujours 0, alors que la MSB d'un entier négatif est toujours 1.

Vous pouvez vérifier la représentation INT_MAX 32 bits:

INT_MAX: 01111111111111111111111111111111

À présent. Pourquoi le cycle utilise sizeof()? Si vous faites simplement le cycle comme je l'ai écrit dans le commentaire: (désolé pour le = manquant dans le commentaire)

for (; a != 0; a >>= 1)
    MSB = a & 1;

vous obtiendrez toujours 1, car C++ ne considérera pas les «bits zéro-pad» (car vous avez spécifié a != 0 comme instruction de sortie) plus élevé que le 1 le plus élevé. Par exemple, pour les entiers 32 bits, nous avons:

int 7 : 00000000000000000000000000000111
                                     ^ this will be your fake MSB
                                       without considering the full size 
                                       of the variable.

int 16: 00000000000000000000000000010000
                                   ^ fake MSB
12
dave
int LSB = value & 1;
int MSB = value >> (sizeof(value)*8 - 1) & 1;
6
Zdeněk Pavlas

D'autres ont déjà mentionné:

int LSB = value & 1;

pour obtenir le bit le moins significatif. Mais il existe un moyen plus triche d'obtenir le MSB que ce qui a été mentionné. Si la valeur est déjà un type signé, il suffit de faire:

int MSB = value < 0;

S'il s'agit d'une quantité non signée, attribuez-la au type signé de la même taille, par exemple. si value a été déclaré comme unsigned, faites:

int MSB = (int)value < 0;

Oui, officiellement, pas portable, comportement indéfini, peu importe. Mais sur tous les systèmes de complément à deux et tous les compilateurs pour lesquels je suis au courant, cela fonctionne; après tout, le bit haut est le bit de signe. Ainsi, si le formulaire signé est négatif, le bit de poids fort est égal à 1, s'il est non négatif, le bit de poids fort est égal à 0. Donc, un test signé pour les nombres négatifs revient à MSB.

1
ShadowRanger

LSB est facile. Juste x & 1.

MSSB est un peu plus compliqué, car les octets peuvent ne pas être 8 bits et sizeof (int) peut ne pas être 4, et il peut y avoir des bits de remplissage à droite.

De plus, avec un entier signé, voulez-vous dire le bit de signe du bit de valeur MS.

Si vous voulez parler du signe, la vie est facile. C'est juste x <0

Si vous voulez parler du bit de valeur le plus significatif, soyez totalement portable.

 int answer  = 0;
 int rack = 1;
 int mask  = 1;

 while(rack < INT_MAX)
 {
    rack << = 1;
    mask << = 1;
    rack |= 1; 
 } 

 return x & mask;

C'est une façon longue de le faire. En réalité

x & (1 << (sizeof (int) * CHAR_BIT) - 2); sera assez portable et votre ints n'aura pas de bits de remplissage.

0
Malcolm McLean