C Побитовые операции влево и сдвиг ИЛИ - PullRequest
0 голосов
/ 03 декабря 2018

Очень коротко, у меня проблемы с пониманием работы этого кода, гораздо эффективнее, чем мои 20 или около того строк, получить тот же результат.Я понимаю, как должен работать левый сдвиг, и побитовый Или, но был бы признателен за небольшое руководство, чтобы понять, как эти два собираются вместе, чтобы заставить работать цикл for.Код предназначен для того, чтобы принимать массив битов (битов) заданного размера (счетчика) и возвращать целочисленное значение битов.

unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
    unsigned res = 0;
    for (size_t i = 0; i < count; i++)
        res = res << 1 | bits[i]; 
    return res;
}

РЕДАКТИРОВАТЬ: По запросу, мое решение для новичка, которое все еще прошло всетесты: добавлен пример возможного назначения битов []

unsigned binary_array_to_numbers(const unsigned *bits, size_t count)
{
        int i, j = 0;
        unsigned add = 0;
        for (i = count - 1; i >= 0; i--){
                if(bits[i] == 1){
                        if(j >= 1){
                                j = j * 2;
                                add = add + j;
                        }
                        else{
                                j++;
                                add = add + j;

                        }
                }
                else {
                        if( j>= 1){
                                j = j * 2;
                        }
                        else{
                                j++;
                        }
                }
        }

        return add;
}

void main(){
        const unsigned bits[] = {0,1,1,0};
        size_t count = sizeof(bits)/sizeof(bits[0]);
        binary_array_to_numbers(bits, count);
}

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

разбивка:

  • каждая операция сдвига влево на двоичном числе эффективно умножает его на 2 0111(7) << 1 = 1110(14)
  • рассмотрим ответ rhubarbdog - операцию можно рассматривать как два отдельных действия,сначала сдвиг влево (умножить на два) и затем ИЛИ с текущим проверяемым битом
  • ПК не различает отображаемое значение и двоичное представление числа

.попробуйте рассмотреть случай, в котором ваш ввод:

bits = {0, 1, 0, 1};
count = 4;
unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
    unsigned res = 0;
    for (size_t i = 0; i < count; i++)
        res = res << 1 // (a)
        res = res | bits[i]; /* (b) according to rhubarbdog answer */
    return res;
}

итерация 0:
- биты [i] = 0;
- (a) res = b0;(сдвиг влево 0)
- (b) res = b0;(побитовое ИЛИ с 0)

итерация 1:
- биты [i] = 1;
- (a) res = b0;(сдвиг влево 0)
- (b) res = b1;(побитовое ИЛИ с 1)

итерация 2:
- биты [i] = 0;
- (a) res = b10;(сдвиг влево на 1 - десятичное значение равно 2)
- (b) res = b10;(побитовое ИЛИ с 0)

итерация 3:
- биты [i] = 1;
- (a) res = b100;(сдвиг влево 1 - десятичное значение равно 4)
- (b) res = b101;(побитовое ИЛИ с 1)

конечный результат для res является двоичным (101) и десятичным (5), как и следовало ожидать. ПРИМЕЧАНИЕ: использование unsigned является обязательным, поскольку значение со знаком будетинтерпретируется как отрицательное значение, если MSB составляет 1

надеюсь, что это поможет ...

0 голосов
/ 03 декабря 2018

рассмотрим их как 2 операции, а я переписываю res= ... как 2 строки

res = res << 1
res = res | 1

Первый проход res устанавливается в 1, в следующий раз он сдвигается *2, потому что этотеперь даже +1

...