2013-10-10 5 views
0

Как слить первые n бит байта с последними 8-n битами другого байта?Объединить первые n бит байта с последними 8-n битами другого байта

Я знаю кое-что, как показано ниже для выбора 3 бита из первого и 5 из второго (который я наблюдал в алгоритме шифрования DES)
zByte=(xByte & 0xE0) | (yByte & 0x1F);
Но я не знаю математику позади, почему мы должны использовать 0xE0 и 0x1F в этом случае. Поэтому я пытаюсь понять детали в отношении каждого бита.

+0

'C#' или 'Java'? Выбери один. И что вы пробовали до сих пор? –

+0

Слияние означает конкатенацию, И? ИЛИ? –

+0

Я знаю как Java, так и C#, не имеет значения, на каком языке я бы получил ответ. Я могу интерпретировать его на другом языке. Я знаю что-то вроде ниже, чтобы выбрать 3 бита из первого и 5 из второго (что я наблюдал в алгоритме шифрования DES) zByte = (xByte & 0xE0) | (yByte & 0x1F); Но я не знаю математики, почему мы должны использовать E0 и 1F в этом случае. Поэтому я пытаюсь понять детали в отношении каждого бита. @RajeshSubramanian Я имею в виду конкатенацию. –

ответ

1

Математика за этими цифрами (0xE0 и 0x1F) довольно просто. Сначала мы используем тот факт, что 0 & <bit> всегда равен 0 и 1 & <bit> всегда равен <bit>.

0x1F является 00011111 двоичным, что означает, что первые 3 бита всегда будут 0 после операции & с другим байтом - и последние 5 бит будут такими же, как и в другом байте. Помните, что каждый 1 в двоичном числе представляет степень 2, поэтому, если вы хотите математически найти маска, это будет сумма 2^x от x = 0 до n-1. Затем вы можете найти противоположную маску (тот, что 11100000), чтобы извлечь первые 3 бит, вам просто нужно вычесть маску из 11111111, и вы получите 11100000 (0xE0).

+0

Получил это .... Спасибо за ваше объяснение. –

5

В C#, это было бы что-то вроде:

int mask = ~((-1) << n); 
    var result = (x & ~mask) | (y & mask); 

т.е. мы строим маску, которая (при п = 5): 000....0011111, то мы объединим (&) один операнд с этой маской, другой операнд с обратным (~) маски и составить их (|).

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

+0

вы можете сделать маску следующим образом: 'int mask = 0xff >> n;' –

+0

Без обид Marc, но способ, которым вы делаете эту маску, выглядит глупым. – harold

+0

@LorentzVedeler при условии, что пример равен n = 17, что не будет работать. Кроме того, для полномасштабной операции он должен быть неподписанным - проблематичным на Java. Но: появляется вариант, который должен работать нормально. Будет обновляться ... лучше? –

1

Это звучит так, будто вы не понимаете, как работает булева арифметика? Если это ваш вопрос, он работает следующим образом:

0xEO и 0x1F являются шестнадцатеричными представлениями чисел. Если перевести эти цифры в двоичном они будут:

0xE0 = 11100000 
0x1F = 00011111 

Кроме & (и) и | (или) являются побитовыми логическими операторами. Чтобы понять логические операторы, сначала запомните 1 = true и 0 = false.

Таблица истинности для & является:

0 & 0 = 0 
0 & 1 = 0 
1 & 0 = 0 
1 & 1 = 1 

Таблица истинности для | это:

0 | 0 = 0 
0 | 1 = 1 
1 | 0 = 1 
1 | 1 = 1 

Итак, давайте разложим ваше уравнение по частям. Сначала мы сначала оценим код в скобках. Мы будем проходить через каждое число в двоичном формате и для оператора &, если каждый операнд имеет 1 в той же позиции бита, которую мы вернем 1. Если либо номер имеет 0, то мы вернем 0. После того, как мы закончим оценку операндов в в скобках мы возьмем 2 результирующих числа и применим | оператором по биту. Если какой-либо номер имеет 1 в той же битовой позиции мы будем возвращать 1. Если оба числа имеют в той же позиции бита в 0 мы возвратимся 0.

Ради обсуждения, давайте скажем, что

xByte = 255 or (FF in hex and 11111111 in binary) 
yByte = 0 or (00 in hex and 00000000 in binary) 

При применении & и | операторов мы будем сравнивать каждый бит поштучно:

zByte = (xByte & 0xEO) | (yByte & 0x1F) 

становится:

zByte = (11111111 & 11100000) | (00000000 & 00011111) 
zByte = 111000000 | 00000000 
zByte = 11100000 

Если вы понимаете это, и как логическое логика работает, то вы можете использовать Marc Gravell «s ответ.

+0

Привет, брат ... Я знаю таблицу истинности, и я знаю, что такое HEX, Binary и любой другой формат. Думаю, ты не понял мой вопрос. Можете ли вы рассказать мне, как вы будете извлекать первые 2 бита или последние 2 бита из байта? Тогда я смогу оттуда ... –

+0

@SudhakarChavali для извлечения бит, вы обычно «и» с маской, точно так же, как все продолжают говорить ... –

0

В Java

С помощью следующей функции мы можем получить первые п биты первого байта и последние 8 п бит второго байта.

общественного класса BitExample {

public static void main(String[] args) { 
    Byte a = 15; 
    Byte b = 16; 
    String mergedValue=merge(4, a, b); 
    System.out.println(mergedValue); 
} 


public static String merge(int n, Byte a, Byte b) { 
    String mergedString = ""; 
    String sa = Integer.toBinaryString(a); 
    String sb = Integer.toBinaryString(b); 

    if(n>sa.length()) { 
     for(int i=0; i<(n-sa.length()); i++) { 
      mergedString+="0"; 
     } 
     mergedString+=sa; 
    }else{ 
     mergedString+=sa.substring(0, n); 
    } 

    if(8*n>sb.length()) { 
     for(int i=0; i<(8*n-sb.length()); i++) { 
      mergedString+="0"; 
     } 
     mergedString+=sb; 
    } 
    return mergedString; 
} 

}

+3

Это, возможно, самый неоправданно запутанный способ выполнения бит ops, который я 'когда-либо видел. Компьютеры ** разработаны ** для работы с битами - все делает так, что строка также известна как «делать это неправильно». –

+0

Хорошо, спасибо за ваш ценный ответ, мы постараемся улучшить мои навыки в манипуляции бит. – pnathan

Смежные вопросы