Подтвердить что ты не робот

Как я могу инвертировать биты беззнакового байта в Java?

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

Например, номер 178 должен преобразовать в букву "М".

178 - 10110010.

Инвертирование всех битов должно давать 01001101, то есть 77 или "M" в качестве символа.

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

4b9b3361

Ответ 1

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

public class Conv {
    public static void main(String[] args) {
        int val = 178;
        val = ~val & 0xff;
        System.out.println((char) val);
    }
}

Ответ 2

~n & 0xff

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

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

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

Integer.reverse(n << 24) & 0xff

Ответ 3

Побитовые операции в 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

Ответ 4

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

int x = [your byte];
x = ~x & 0xFF;

Ответ 5

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

  • Прочитайте значение как int (32 бита в java). Он может считаться отрицательным, но мы все равно заботимся о нижних 8 битах. int i = scanner.nextByte();
  • Сделайте инверсию как int, используя побитовые операторы (как вы говорите, даст вам 1s как бит старшего порядка: i = ~i;
  • Потеряйте биты высокого порядка с логическим И: 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); 

Ответ 6

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;
}

Ответ 7

Вот байты 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;