Неожиданный результат после добавления - PullRequest
0 голосов
/ 27 декабря 2018

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

Я столкнулся с ошибкой при запуске первой строки кода ниже.

Неверные результаты

short regPair = (short) ( (byte1 << 8) + (byte2) );

Правильные результаты

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

Ожидаемые результаты: AAAAAAAABBBBBBBB, где A представляет биты из byte1 и B представляетбиты из byte2.

Используя 1-ю строку кода, я получу типичное добавление между сдвинутым в битах байтом 1 и добавленным в него байтом 2.

Пример неправильных результатов

byte1 = 11, byte2 = -72

result = 2816 -72
       = 2744

При использовании строки кода, которая дает ожидаемые результаты, я могу получить правильный ответ 3000. Мне интересно, почему для byte2 необходима битовая маскировка.Я думаю, что перед добавлением он преобразует byte2 в двоичный файл, а затем выполняет двоичное добавление с обоими байтами.

Ответы [ 4 ]

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

В обоих случаях значения байтов повышаются до int в выражении при его вычислении.

byte byte1 = 11, byte2 = -72;
short regPair = (short) ( (byte1 << 8) + (byte2) );

(2816) + (-72) = 2744

И даже в приведенном ниже выражении байт выражения превращается в int

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

2816 + 184 = 3000

Здесь в этом выражении нет объединения двух байтов, как это было выражено в приведенном вышеquestion- AAAAAAAABBBBBBBB, где A представляет биты из байта 1, а B представляет биты из байта 2.

На самом деле -7 & 255 дает 184, которые добавляются к 2816 для получения 3000.

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

Так что я полностью забыл, что byte опознан в Java, поэтому при выполнении математических операций с переменной этого типа данных он принимает интерпретацию со знаком, а не прямое значение битов.Выполняя byte2 & 0xFF, Java преобразует значение байта со знаком в целое число без знака со всеми, кроме первых 8 битов, равными 0.Поэтому вы можете правильно выполнить двоичное сложение.

значение байта со знаком 0x11111111 = -1

значение байта без знака 0x11111111 = 255

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

В неправильном случае byte2 повышается до int из-за оператора +.Это не означает просто добавление нескольких нулей в начало двоичного представления byte2.Поскольку целочисленные типы представлены в дополнении до двух в Java, будет добавлено 1s .После повышения byte2 становится:

1111 1111 1111 1111 1111 1111 1011 1000

Выполнив & 0xFF, вы заставляете повышение до int сначала , затем сохраняете наименее значимые 8 битов: 1011 1000 и сделать все остальное 0.

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

Напечатайте промежуточное значение непосредственно, чтобы увидеть, что происходит.Например,

System.out.printf("%d %s%n", ((byte) -72) & 0xFF, Integer.toBinaryString(((byte) -72) & 0xFF));

Я получаю

184 10111000

Таким образом, правильный код фактически добавляет 184 (не вычитая 72).

...