it-swarm.com.ru

Проверьте значение младшего значащего бита (LSB) и старшего значащего бита (MSB) в C/C++

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

21
delaccount992
//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

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

НТН.

21
Armen Tsirunyan

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

#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 1 или нет.

edit: найти MSB.

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

Чтобы найти MSB, в следующем фрагменте мы сосредоточимся на применении сдвига вправо, пока MSB не будет ANDed с 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++ не будет считать «биты нулевой точки» (потому что вы указали 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
12
dave
int LSB = value & 1;
int MSB = value >> (sizeof(value)*8 - 1) & 1;
6
Zdeněk Pavlas

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

int LSB = value & 1;

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

int MSB = value < 0;

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

int MSB = (int)value < 0;

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

1
ShadowRanger

LSB это просто. Просто х & 1.

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

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

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

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

 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); будет достаточно переносимым, и ваши int не будут иметь битов заполнения.

0
Malcolm McLean