как проверить, включены ли хотя бы три из последних четырех битов (LSB) - PullRequest
2 голосов
/ 13 января 2010

Я пытался сделать это в C:

    int val = 0xCAFE;
int uc = val & 14;


if (val & 15 == 15 || val & 7 == 7 || val & 11 == 11|| val & 13 == 13 || val & 14 == 14){
    printf("asdjfkadscjas \n");
}

Однако это не печатает случайную строку, как следует. Работало на 15,7,11,13 тыс.

Если кто-нибудь знает лучший способ, который будет полезен. Я плохо с побитовым оператором.

Спасибо

Ответы [ 12 ]

21 голосов
/ 13 января 2010

Альтернативное решение: Вы можете поместить все свои числа в таблицу поиска в двоичном коде:

int AtleastThreeBits (int a)
{
  return (0xe880>>(a&15))&1;
}

Каждый бит магического числа представляет ответ. В константе 0xe880 установлены биты 7,11,13,14 и 15. Вы выбираете правильный бит с помощью сдвига и маскируете его.

Это не так читабельно, как ваше решение, но быстрее ..

6 голосов
/ 13 января 2010

У вас проблема с приоритетом оператора, а не с операцией. == имеет более высокий приоритет, чем &:

if ((val & 15) == 15 || (val & 7) == 7 || ...

Кроме того, вам не нужно проверять 15.

6 голосов
/ 13 января 2010
if (((value & 1 ? 1 : 0) +
     (value & 2 ? 1 : 0) +
     (value & 4 ? 1 : 0) +
     (value & 8 ? 1 : 0)) >=3)
2 голосов
/ 13 января 2010

Вы можете использовать перенос из дополнения, чтобы «заполнить» 1-ю 0-битную «дыру» в номере. Мы допускаем не более одного из них в нижнем полубайте, поэтому при объединении исходного значения и «заполненной» версии с | будет получен нижний полубайт со всеми 1-битами в этом случае:

if (((val | (val + 1)) & 15) == 15)

Я думаю, что на данный момент у этого наименьшего количества операций из всех (без таблиц поиска) - нет, на самом деле У умной "таблицы поиска на месте" Нильса Пипенбринка еще меньше!

2 голосов
/ 13 января 2010

Вы можете попробовать справочную таблицу! Тогда вы можете легко изменить свой порог.

static int nibbleCounts[] = { 0, 1, 1, 2,
                              1, 2, 2, 3,
                              1, 2, 2, 3,
                              2, 3, 3, 4 };
if (nibbleCounts[value & 0xF] >= 3)
    puts ("Hello!");
2 голосов
/ 13 января 2010

Оператор сравнения имеет приоритет над побитовым оператором и оператором, поэтому ставьте круглые скобки вокруг оператора &:

if( (val & 15) == 15 || (val & 14) == 14 || ... ) {
    printf( "random string...\n" );
}
1 голос
/ 13 января 2010
int x = val & 0x0f;    // mask to keep only the interesting bits

switch (x) {
    case  7:  // 0b0111 ==  7
    case 11:  // 0b1011 == 11
    case 13:  // 0b1101 == 13
    case 14:  // 0b1110 == 14
    case 15:  // 0b1111 == 15
        // at least 3 bits are set
        // do whatever you need, like

        printf("asdjfkadscjas \n");
        break;
}

Это не особенно умно, но я думаю, что следующая булавочная головка, которая придет и рассмотрит код, не будет иметь проблем с выяснением того, что является намерением и является ли оно правильным.И это действительно большой плюс, когда эта булавка - то, что я пытаюсь выяснить, какого черта я делал в этой функции на прошлой неделе.

1 голос
/ 13 января 2010

Простой способ сделать это, который также ясно показывает ваши намерения, будет:

if (!!(val & 0x01) + !!(val & 0x02) + !!(val & 0x04) + !!(val & 0x08) >= 3)
0 голосов
/ 15 января 2010

Интересная касательная к этому вопросу - думаю, я знаю своего рода умный ответ на вопрос «Сколько битов установлено в этом значении»

#include <stdint.h>
#include <stdio.h>

uint8_t NumBitsSet(uint32_t value){
   uint8_t num_bits_set = 0;
   while(value != 0){
     value = value & (value-1);
     num_bits_set++;
   }

   return num_bits_set;
}

int main(int argc, char *argv[]){
  uint32_t value = 2147483648;
  printf("numbits set in %x = %d", value, NumBitsSet(value));
  return 0;
}

Вы можете использовать это как основу для определения, установлен ли точно один бит, хотя вам нужно сделать специальную проверку для нуля.

uint8_t exactly_one_bit_set = (value & (value-1)) == 0 ? 1 : 0;

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

0 голосов
/ 13 января 2010
unsigned nNumOfBitEnabled=0;
    for(unsigned nBit=0; nBit<4; ++nBit)
    {
        // Check bit state
        if ((val >> nBit) & 0x1)
        {
            ++nNumOfBitEnabled;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...