Шестнадцатеричный: установить 8-битный байт в int
В Java:
У меня есть 32-битное число, данное мне в шестнадцатеричной форме. Мне дали конкретный номер байта (0-3, 0 для младшего байта) и сказали, что мне нужно заменить этот байт другим байтом, также предоставленным мне в шестнадцатеричной форме. Пример: 32-разрядное число 0xAAA5BBC6, замените байт 1 на 0x17, чтобы получить 0xAAA517C6.
Я не могу использовать любое приведение, умножение, сложение, вычитание или условные выражения. Я не могу написать какие-либо вспомогательные методы или вызвать любой другой метод из этого или другого файла для реализации любого метода. Кроме того, это должно быть написано в одной строке кода.
Я считаю, что я должен использовать маскировку, но я не могу понять, с чего начать. Учитывая номер байта, как я могу изменить все 8 битов. Переключить один из них или включить легко, но переключить все 8 бит, чтобы получить определенное значение?
3 ответа
В одной строке, предполагая, что байты считаются из младшего байта:
int updatedValue = originalValue & ~(0xFF << (byteNumber << 3)) | ((((int)newByte) & 0xFF) << (byteNumber << 3));
Куда:originalValue
ваше оригинальное 32-битное целоеnewByte
это байт, который вам дан для замены старого байтаbyteNumber
это номер байта (0-3)
код делает следующее:
создайте маску для "удаления" старого байта (очистите биты этого байта). Для того, чтобы создать маску:
- создать маску байта из всех установленных битов (все в 1)
0xFF
- сместите эту маску в положение байта, который нужно "удалить", он должен быть в 8 раз больше количества байтов, которые нужно "удалить". Поскольку я не могу умножить (часть ваших ограничений), то я смещу это число на 3 бита влево (что эквивалентно умножению на 8, помните, что смещение битов на одну позицию влево равнозначно умножению на 2, поэтому смещение на 3 будет 2 * 2 * 2 = 8) это делается с помощью этого фрагмента кода:
(byteNumber << 3)
- "переключать" биты маски с
~
Итак, у меня есть маска для "удаления" байта:~(0xFF << (byteNumber << 3))
в этот момент ваша маска будет, скажем,FFFF00FF
если вы хотите очистить байт #1
- создать маску байта из всех установленных битов (все в 1)
выполнить побитовую операцию между исходным номером и маской, созданной на первом шаге:
~(0xFF << (byteNumber << 3))
- создайте 32-битное целое число с новым байтом и сместите его биты в позицию байта. Опять же, смещение сделано с
(byteNumber << 3)
который уже был объяснен. - выполнить побитовую или побитовую операцию с результатом второго шага, чтобы установить биты нового байта (это строка кода, последний шаг)
Теперь причина, по которой я делаю ((int)newByte) & 0xFF)
вместо просто ((int)newByte))
или просто newByte
является то, что JVM способствует int
Оператор byte
перед выполнением операции <<
, это может иметь нежелательные последствия, если ваш newByte больше 0x7F (например, значение 0x80
будет брошен на int
как 0xFFFFFF80
вместо 0x00000080
). При выполнении ((int)newByte) & 0xFF)
Я делаю повышение в int
на всякий случай и очистить ненужные биты на всякий случай.
Взгляните на следующий пример:
input = AA A5 BB C6 (in hex)
input = 10101010 10100101 10111011 11000110 (in binary)
mask = FF FF 00 FF (in hex)
mask = 11111111 11111111 00000000 11111111 (in binary)
-------------------------------------------------------
input = 10101010 10100101 00000000 11000110 (bitwise AND)
replace = FF FF 17 FF (in hex)
replace = 11111111 11111111 00010111 11111111 (in binary)
-------------------------------------------------------
input = 10101010 10100101 00010111 11000110 (bitwise OR)
input = AA A5 17 C6 (in hex)
Последняя строка - ваш желаемый результат. Как видите, есть две побитовые операции, И и ИЛИ. Вы должны изучить это много, чтобы знать, как работают.
Как насчет того, чтобы создать метод (или конструктор класса), целью которого является именно анализ шестнадцатеричного значения и его преобразование в любой тип данных, который вы хотите. Я настоятельно рекомендую вам прочитать о переводе данных или посмотреть видео об этом на YouTube и посмотреть, как это может иметь отношение к вашему делу. Удачи! - Макс