Как я могу инвертировать биты беззнакового байта в Java?
Я пытаюсь написать декодер для очень простого типа шифрования. Номера с 0-255 вводятся через сканер, биты инвертируются, а затем преобразуются в символ и печатаются.
Например, номер 178 должен преобразовать в букву "М".
178 - 10110010.
Инвертирование всех битов должно давать 01001101, то есть 77 или "M" в качестве символа.
Основная проблема заключается в том, что, насколько я могу судить, Java не поддерживает неподписанные байты. Я мог читать значения как int или short, но тогда значения будут отключены во время преобразования из-за дополнительных бит. В идеале я мог бы просто использовать побитовый оператор дополнения, но я думаю, что в конечном итоге получаю отрицательные значения, если я сделаю это с помощью подписанных чисел. Любые идеи о том, как я должен подходить к этому?
Ответы
Ответ 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;