Проверьте значение младшего значащего бита (LSB) и старшего значащего бита (MSB) в C / C ++ - PullRequest
21 голосов
/ 11 июля 2011

Мне нужно проверить значение младшего значащего бита (LSB) и старшего значащего бита (MSB) целого числа в C / C ++. Как бы я это сделал?

Ответы [ 5 ]

21 голосов
/ 11 июля 2011
//int value;
int LSB = value & 1;

В качестве альтернативы (который не является теоретически переносимым, но практически таковым является - см. Комментарий Стива)

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

Подробности: Вторая формула проще.Оператор% является оператором остатка.LSB числа равен 1, если это нечетное число, и 0 в противном случае.Итак, мы проверяем остаток от деления на 2. Логика первой формулы такова: число 1 в двоичном виде:

0000...0001

Если вы двоично-И это с произвольным числом, все битырезультат будет 0, кроме последнего, потому что 0 И все остальное равно 0. Последний бит результата будет 1, если последний бит вашего числа был 1, потому что 1 & 1 == 1 и 1 & 0 == 0

Этот является хорошим руководством для побитовых операций.

HTH.

13 голосов
/ 11 июля 2011

Вы можете сделать что-то вроде этого:

#include <iostream>

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

Таким образом, вы AND ваша переменная с LSB, потому что

3: 011
1: 001

в 3-битном представлении.Таким образом, будучи AND:

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

Вы сможете узнать, равен ли LSB единице.

изменить: найти MSB.

Прежде всего прочитайте Endianess статью, чтобы договориться о том, что означает MSB.В следующих строках мы предполагаем обработать запись с прямым порядком байтов.

Чтобы найти MSB, в следующем фрагменте мы сосредоточимся на применении правого сдвига, пока MSB не будет AND ed с1.Рассмотрим следующий код:

#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;
}

Если вы напечатаете MSB вне цикла, вы получите 0.Если вы измените значение a:

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

MSB будет 1, потому что его 32-битное представление:

UINT_MAX: 11111111111111111111111111111111

Однако, если вы это сделаетето же самое с знаковым целым числом будет другим.

#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;
}

Как я уже сказал в комментарии ниже, MSB из положительного целого числа всегда 0, тогда как MSB из отрицательного целого числа всегда 1.

Вы можете проверить 32-битное представление INT_MAX:

INT_MAX: 01111111111111111111111111111111

Теперь.Почему цикл использует sizeof()?Если вы просто выполните цикл, как я написал в комментарии: (извините за =, отсутствующий в комментарии)

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

вы всегда получите 1, потому что C ++ не будет считать 'нольбиты -pad '(потому что вы указали a != 0 в качестве оператора выхода) выше самого высокого 1.Например, для 32-битных целых чисел у нас есть:

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

int 16: 00000000000000000000000000010000
                                   ^ fake MSB
6 голосов
/ 03 июня 2013
int LSB = value & 1;
int MSB = value >> (sizeof(value)*8 - 1) & 1;
2 голосов
/ 09 января 2016

Другие уже упоминали:

int LSB = value & 1;

для получения наименее значимого бита. Но есть более обманчивый способ получить MSB, чем было упомянуто. Если значение уже имеет тип со знаком, просто выполните:

int MSB = value < 0;

Если это количество без знака, приведите его к типу со знаком того же размера, например если value было объявлено как unsigned, выполните:

int MSB = (int)value < 0;

Да, официально, не переносимо, неопределенное поведение, что угодно. Но на каждой системе комплемента каждой из двух и на каждом компиляторе, о котором я знаю, это работает; в конце концов, старший бит является знаковым битом, поэтому, если подписанная форма отрицательна, то MSB равен 1, если он неотрицательный, MSB равен 0. Поэтому удобно, что знаковый тест для отрицательных чисел эквивалентен извлечению MSB.

0 голосов
/ 19 февраля 2017

LSB легко. Просто х & 1.

MSSB немного сложнее, поскольку байты могут не быть 8 битами, а sizeof (int) может не быть 4, а справа могут быть биты заполнения.

Кроме того, со знаком целого числа вы имеете в виду знаковый бит бита значения MS.

Если вы имеете в виду бит знака, жизнь проста. Это просто х <0 </p>

Если вы имеете в виду бит старшего значащего значения, чтобы быть полностью переносимым.

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

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

 return x & mask;

Это многословный способ сделать это. На самом деле

x & (1 << (sizeof (int) * CHAR_BIT) - 2); будет достаточно портативным, и у ваших инттов не будет битов заполнения. </p>

...