Печать бит Часть II


Не могли бы вы предложить способы сделать это более просто?

/*
 * Next write a function invert(x,p,n) that returns x with the n bits
 * that begin at position p inverted, leaving the others unchange
 */

void printbits(unsigned x) {
    size_t size_of_int = sizeof(int) << 3;
    unsigned mask = 1;
    int i = 0;
    for(i = 1; i <= size_of_int; ++i, x >>= 1) {
       ((x & mask) == 0) ? printf("0") : printf("1");
       ((i & 3)==0) ? printf(" ") : printf("%s","");
    }
    printf("\n");
}

void invert(unsigned x, unsigned p, unsigned n) {
    printbits(((~((((~(~0 << n) << p))) & x)) & (~(~0 << n) << p)) | (x & ~(~(~0 << n) << p)));
}

int main(int argc, char *argv[]) {
    unsigned input=3082676239, begin=15, nbits=5;
    invert(input, begin, nbits);
    return(0);
}

Прежде чем ездовой спорт объединяет части это то, что я получаю на выходе:

              x = 1111 0000 0001 0111 1011 1101 1110 1101 
===================================================================
          mask0 = 1111 0000 0001 0110 0000 1101 1110 1101 
          mask1 = 1111 1111 1111 1110 0100 1111 1111 1111 
          mask2 = 0000 0000 0000 0001 1111 0000 0000 0000 
===================================================================
         output = 1111 0000 0001 0110 0100 1101 1110 1101


988
7
задан 17 ноября 2011 в 09:11 Источник Поделиться
Комментарии
2 ответа

Может быть:

void invert2(unsigned x, unsigned p, unsigned n) {
printbits((~(~0 << n) << p) ^ x);
}

1
ответ дан 17 ноября 2011 в 09:11 Источник Поделиться

В то время как код @palacsint может работать, он не впечатлил меня как образец ясности. Думаю, я бы начала с того, что вычитанием 1 из числа очищает наименее значимый бит, который был установлен, и устанавливает все менее значащих битов. Если мы начнем с номером, который имеет только один бит, этот бит будет очищен, а все менее значимые биты будут установлены. Исходя из этого, становится маска из N битов довольно прост: возьмите 1, сдвиг ее влево n бит, а затем вычесть 1.

Например, рассмотреть вопрос о создании 5-битовая маска в виде 16-битного числа:

0000 0000 0000 0001    // 1
0000 0000 0010 0000 // 1 << 5
0000 0000 0001 1111 // (1<<5)-1

Как только мы это, мы можем переместить его слева п битов, чтобы получить его в правильном положении, и гаммирования с входным:

unsigned invert(unsigned x, unsigned p, unsigned n) { 
unsigned mask = ((1u << n) - 1u) << p;
return x ^ mask;
}

Пару незначительных моментов:


  1. Я снял печать с вывороткой -- ИМО, печатая результат должен быть отдельный.

  2. Для этого необходимо, чтобы н.

Я думаю, что печать может быть немного упрощен, а также. Хотя "тест для кратно 4" внутри цикла не работает, я думаю, по крайней мере в этом случае вложенный цикл делает цель яснее:

void print(unsigned x) { 
static const int group_size = 4;
int group, j;

for (group = 0; group < size_of_int / group_size; group++) {
for (j=0; j<group_size; j++, x >>= 1)
printf("%c", (x & 1) + '0');
printf(" ");
}
}

Другая возможность, что может быть стоит задуматься, будет небольшая таблица подстановки для преобразования 4 бита:

void print(unsigned x) { 
static const int group_size = 4;
// inverted order because you're printing the LSB first.
static const char *outputs[] = {
"0000", "1000", "0100", "1100", "0010", "1010", "0110", "1110",
"0001", "1001", "0101", "1101", "0011", "1011", "0111", "1111"
};
int group;

for (group=0; group<size_of_int / group_size; group++, x >>= 4)
printf("%s ", outputs[x & 0xf]);
}

3
ответ дан 18 ноября 2011 в 06:11 Источник Поделиться