@synapse_people

Как работает этот код(побитовые сдвиги)?

В общем имеется код на языке JAVA(язык оригинала другой, но было портированно в JAVA), необходимо понять как именно он работает.. Суть примерно такая: чтобы не использовать каждый раз 1 байт на передачу значения типа boolean было предложено использовать карту этих boolean и потом вычитывать по очереди их, таким образом в 1 байт влезает 8 boolean значений(1 бит = 1 boolean). Сетевой пакет примерно такой структуры: Карта значений boolean-ов, сами данные.

МОМЕНТ НОМЕР ОДИН Модификация позиций.
Следующий фрагмент кода присутствует в двух методах(getBit/setBit) представленных ниже. Мне понятно, что это преобразование(сдвиг?) позиций, но не могу понять зачем.
int _local2 = (position >> 3);
int _local3 = (7 ^ (position & 7));

Вопрос: Что именно делает первая и вторая строка, и зачем?

МОМЕНТ НОМЕР ДВА Чтение 1 бита(boolean) из буффера.
boolean getBit(int position) {
*КОПИПАСТ ИЗ МОМЕНТА НОМЕР ОДИН*
*тут ставится позиция буффера в _local2*
return !(((this.map.readByte() & (1 << _local3)) == 0));
}

Вопрос: Что делает последняя строка и зачем?

МОМЕНТ НОМЕР ТРИ Запись boolean в буффер.
void setBit(int position, Boolean value) {
*ТУТ ТОЖЕ КОПИПАСТ ИЗ МОМЕНТА НОМЕР ОДИН*
*ТУТ ВЫПОЛНЯЕТСЯ ПРОВЕРКА, ЕСЛИ В БУФФЕРЕ НЕТ МЕСТА ДЛЯ ЗАПИСИ СЛЕДУЮЩЕГО БИТА, ТО АЛЛОЦИРУЕТСЯ 1 БАЙТ*
*тут ставится позиция буффера в _local2*

		if (value) {
			this.map.writeByte((byte) ((this.map.readByte(_local2) | (1 << _local3))));
		} else {
			this.map.writeByte((byte) ((this.map.readByte(_local2) & (0xFF ^ (1 << _local3)))));
		}
	}

Вопрос: Что делает последний блок IF и его бранчи, и зачем?

Заранее Спасибо, за развернутые ответы!
Решением отмечу только то, что реально поможет максимально упростить код при этом, чтобы результат кодирования был понятен удаленному серверу(к нему НЕТ доступа). Спасибо.

АП: Могу предоставить код кодека, кодирующего эту карту. Но задача стоит именно понять как сама карта работает, кодек просто получает байты из этой карты булаенов и дописывает ее длинну в первых битах, все.
=========================================================
Упрощенный вариант кода(вместо буффера - массив из 2 байт), есть сравнение с BitSet.
private static boolean getBit(byte[] ba, int position) {
		int _local2 = (position >> 3);
		int _local3 = (7 ^ (position & 7));

		byte b = ba[_local2];

		return !((b & (1 << _local3)) == 0);
	}

	private static byte[] setBit(byte[] ba, int position, boolean value) {
		int _local2 = (position >> 3);
		int _local3 = (7 ^ (position & 7));

		if (value) {
			ba[_local2] = (byte) (ba[_local2] | (1 << _local3));
		} else {
			ba[_local2] = (byte) (ba[_local2] & (0xFF ^ (1 << _local3)));
		}

		return ba;
	}

	static String toBinary(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length * Byte.SIZE);
		for (int i = 0; i < Byte.SIZE * bytes.length; i++)
			sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
		return sb.toString();
	}

	public static void main(String[] args) {
		
		

		byte[] map = new byte[2];
		map = setBit(map, 0, true);
		map = setBit(map, 1, false);
		map = setBit(map, 2, true);
		map = setBit(map, 3, true);
		map = setBit(map, 4, true);
		map = setBit(map, 14, false);
		map = setBit(map, 15, true);

		System.out.println(toBinary(map));// 1011100000000001 RIGHT!

		System.out.println(getBit(map, 0));// true
		System.out.println(getBit(map, 1));// false
		System.out.println(getBit(map, 2));// true
		System.out.println(getBit(map, 3));// true
		System.out.println(getBit(map, 4));// true
		System.out.println(getBit(map, 14));// false
		System.out.println(getBit(map, 15));// true


BitSet bitSet = new BitSet();
		
		bitSet.set(0, true);
		bitSet.set(1, false);
		bitSet.set(2, true);
		bitSet.set(3, true);
		bitSet.set(4, true);
		bitSet.set(14, false);
		bitSet.set(15, true);
		
		System.out.println(toBinary(bitSet.toByteArray()));//0001110110000000 WTF??
}
  • Вопрос задан
  • 572 просмотра
Пригласить эксперта
Ответы на вопрос 3
romy4
@romy4
Exception handler
this.map.writeByte((byte) ((this.map.readByte(_local2) & (0xFF ^ (1 << _local3)))));
прочитать байт _local2 и сравнить его с обратной маской в зависимости от бита по позиции _local3, затем записать получившийся байт. как тут можно понять, для чего это?))
Ответ написан
Комментировать
vt4a2h
@vt4a2h
Senior software engineer (C++/Qt/boost)
Кто-то за вас будет разбираться... серьезно?
Вот посмотрите да разбиритесь: https://en.wikipedia.org/wiki/Bitwise_operation . Тем более, что вы лучше понимаете что там делается и зачем в плане бизнес-логики.
Ответ написан
Комментировать
@synapse_people Автор вопроса
Пост обновлен
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы