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?
//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.
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 AND
ed 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
int LSB = value & 1;
int MSB = value >> (sizeof(value)*8 - 1) & 1;
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.
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.