Как я могу инвертировать биты беззнакового байта в Java? - PullRequest
16 голосов
/ 24 июля 2010

Я пытаюсь написать декодер для очень простого типа шифрования. Числа от 0 до 255 вводятся через сканер, биты инвертируются, а затем преобразуются в символ и печатаются.

Например, число 178 следует преобразовать в букву «М».

178 - 10110010.

Инвертирование всех битов должно дать 01001101, что составляет 77 или «М» как символ.

Основная проблема, с которой я столкнулся, состоит в том, что, насколько я могу судить, Java не поддерживает неподписанные байты. Я мог бы читать значения как int или short, но тогда значения будут отключены во время преобразования из-за дополнительных битов. В идеале я мог бы просто использовать оператор побитового дополнения, но я думаю, что в итоге получу отрицательные значения, если я сделаю это со знаковыми числами. Любые идеи о том, как я должен подходить к этому?

Ответы [ 7 ]

14 голосов
/ 24 июля 2010

Я бы просто использовал те, которые дополняли, и избавлялся от других битов, используя двоичные и.

public class Conv {
    public static void main(String[] args) {
        int val = 178;
        val = ~val & 0xff;
        System.out.println((char) val);
    }
}
11 голосов
/ 24 июля 2010
~n & 0xff

~ выполняет дополнение и неявно преобразует в целое число, как и все числовые операции, затем & 0xff маскирует все, кроме младших 8 бит, чтобы получить значение без знака, снова как целое число.

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

Вы можете использовать Integer.reverse() (не проверено):

Integer.reverse(n << 24) & 0xff
4 голосов
/ 24 июля 2010

Битовые операции в Java определены для int, поэтому имеет смысл работать с int, а не byte. Вы можете использовать Scanner.nextInt вместо Scanner.nextByte. Вам следует проверить вводимые пользователем данные, чтобы убедиться, что все введенные целые числа находятся в диапазоне от 0 до 255, и отображать соответствующее сообщение об ошибке, если встречается число вне диапазона.

Как только вы сохранили число в целом числе, переверните младшие 8 бит, которые вы можете XOR с 0xff. Это должно работать так, как вы ожидаете для всех входов от 0 до 255:

x ^= 0xff;

Пример:

String input = "178 0 255";
Scanner s = new Scanner(input);
while (s.hasNextInt()) {
    int x = s.nextInt();
    if (x < 0 || x > 255) {
        System.err.println("Not in range 0-255: " + x);
    } else {
        x ^= 0xff;
        System.out.println(x);
    }
}

Результат:

77
255
0
2 голосов
/ 24 июля 2010

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

int x = [your byte];
x = ~x & 0xFF;
0 голосов
/ 08 июля 2014
private byte reverseBitsByte(byte x)
{
    int intSize = 8;

    byte y = 0;
    for (int position = intSize - 1; position >= 0; position--)
    {
        y += ((x & 1) << position);
        x >>= 1;
    }
    return y;
}
0 голосов
/ 26 января 2012

Вот байты Java, отсортированные по двоичному представлению (от 00000000 до 11111111):

0, 1, 2, .., 126, 127, -128, -127, .., -2, -1

00000000 равно 0, 11111111 равно -1

Инвертированный 0 - это -1, инвертированный 1 - это -2, ..., инвертированный 127 - это -128. Таким образом, если вы хотите инвертировать биты байта Java, вы должны получить свой байт с противоположным знаком и вычесть один:

byte myByte = 123;
byte myInvertedByte = -myByte-1;
0 голосов
/ 24 июля 2010

Самый простой способ сделать это - три этапа:

  1. Считать значение как целое число (32 бита в Java). Может показаться отрицательным, но в любом случае нам важны только 8 младших битов. int i = scanner.nextByte();
  2. Делайте инверсию как int, используя побитовые операторы (как вы говорите, вы получите 1 с как биты старшего разряда: i = ~i;
  3. Потерять старшие биты с помощью логического И: i = i & 0xFF;

Затем просто используйте результат как символ (который на самом деле составляет 16 бит в Java, но мы будем использовать только 8 из них):

char c=(char)a;
System.out.println(c); 

Все вместе:

int i = scanner.nextByte(); // change this to nextInt() depending on file format
i = ~i;
i = i & 0xFF;
char c=(char)a;
System.out.println(c); 
...