Хранение одного бита - PullRequest
       7

Хранение одного бита

3 голосов
/ 05 февраля 2012

Мой вопрос может показаться немного любительским, но я нигде не могу найти ответ в Интернете.Некоторое время назад один из разработчиков Minecraft рассказал о том, как двери хранятся в игре ( ссылка ).Он сказал, что они хранятся с использованием 4 бит.2 для ориентации, 1 для верхней или нижней части и один для открытой или закрытой.Это заставило меня задуматься о том, как ты это делаешь.Вы видите, что сохранение байта делает с тех пор, потому что один символ ASCII является байтом.Однако вы не можете просто записать какой-либо символ в файл, который является только битом, потому что символы не могут быть сохранены только с одним битом, они хранятся в виде байта.Я знаю, что бит выражается как 1 или 0. Однако запись 1 или 0 в файл даст вам 4 байта, а не один бит.Так как это сделать?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 05 февраля 2012

Скорее всего, это делается путем объединения различных двоичных флагов.Чтобы дать вам четкое объяснение, вы должны понимать, как числа представляются побитовым образом.По сути, это все равно что считать в десятичном виде с той лишь разницей, что доступны только два числа.Ниже приведен пример (десятичные числа 0-16 в их двоичном представлении).

Decimal     Binary

0           0
1           1
2           10
3           11
4           100
5           101
6           110
7           111
8           1000
9           1001
10          1010
11          1011
12          1100
13          1101
14          1110
15          1111
16          10000

Именно так ваш компьютер хранит числа.Вы также должны получить базовые знания о побитовых операторах.Допустим, у вас есть две строки по 8 битов, которые выглядят следующим образом:

10101010
01011111

Если вы объедините эти две строки с помощью побитового оператора или оператора - "|"- бит вывода x равен 1, если бит x строки 1 равен 1 или бит x строки 2 равен 1. Таким образом, в нашем случае результат будет выглядеть следующим образом:

11111111

По битам иОператор (&) проверяет, равен ли бит строки 1 строки 1 1, а битом строки 2 x 1. В нашем случае это вывод:

00001010

Побитовый оператор xor (исключая или)) проверяет, равен ли бит одной строки х 1. Наш результат будет выглядеть следующим образом:

11110101

По сути, разработчики Minecraft сделали, что они определили несколько флагов.они должны были хотеть состояние двери, когда верхняя часть двери обращена на запад и открыта, они написали бы это так:

byte state = ORIENTATION_WEST | PART_UPPER | STATE_OPEN;

По битам это будет выглядеть так:

Что в итоге будет иметь вид:

00001110 (west, upper part, open)

Хотя, как вы сказали, используются только первые 4 бита байта, вы не можете просто сохранить биты.Скорее всего, весь байт будет сохранен.

2 голосов
/ 05 февраля 2012

Вы правы, вы не можете сделать это, когда все, что вам нужно, это сохранить один бит: вы должны сохранить хотя бы байт.

Однако, если у вас есть несколько элементов, каждый из которых занимает менее байта, вы можете упаковать несколько элементов вместе в один байт.

Используя 4-битные двери в качестве примера, предположим, что вы хотите хранить информацию о двух дверях. Вам нужно восемь бит для этого, и это один байт. Вы можете сохранить первую дверь в нижних четырех битах, а вторую дверь в верхних четырех битах. Когда вам нужно узнать состояние первой двери, замаскируйте вторую, применив операцию twoDoorsInOneByte & 0x0F: она удаляет верхнюю часть байта. Когда вам нужна вторая дверь, сдвиньте ее биты в положение, используя сдвиг влево: (twoDoorsInOneByte >> 4) & 0x0F: он перемещает верхние четыре бита в верхние четыре бита и очищает те, которые находятся в верхней половине байта, в случае, если ваше значение получит вздох-продлены.

Наконец, в C у вас есть другая опция: вы можете использовать битовые поля . Это может быть полезно, когда вы хотите упаковать элементы произвольной длины в несколько слов, чтобы сэкономить место. Обратите внимание, что этот метод следует применять с осторожностью, когда экономия относительно высока или слишком мало памяти (например, вы пишете встроенный код для 8-битного микроконтроллера).

1 голос
/ 05 февраля 2012

Определите:

DOOR_UP = 0x01
DOOR_LEFT = 0x02
DOOR_BIG = 0x04
DOOR_SMALL = 0x08
DOOR_RED = 0x10
DOOR_BLUE = 0x20
DOOR_GREEN = 0x40

Если вам нужна левая маленькая зеленая дверь, напишите

def door := DOOR_LEFT or DOOR_SMALL or DOOR_GREEN (Z** or some generic language)
byte door = DOOR_LEFT | DOOR_SMALL | DOOR_GREEN;  (C++)

Чтобы проверить, является ли зеленая дверь "спросить":

door & DOOR_GREEN

Ноль означает не зеленый.Ненулевое значение (на самом деле, DOOR_GREEN) означает ЗЕЛЕНУЮ дверь

Добавление:

Вы можете даже собрать два числа по 0-7 в один байт.Эта же идея используется в ZX Spectrum (1982) для определения цвета символа:

Xbbbfff (bbb - background color, fff - foreground color, X - for blink)

Чтобы установить bkg color 5 и fgd на 4, вы используете:

color = 5 << 3 | 4 

Чтобы получить фониспользование цвета:

( color >> 3 ) & mask(0x7) -> 5

Если вы создаете игры, каждый нсек важен.Старайтесь избегать использования битовых операций всякий раз, когда вы можете:)

0 голосов
/ 05 февраля 2012

Почти все современные компьютеры являются адресуемыми в байтах, то есть вы можете адресовать (указывать) только один байт памяти и ничего меньшеТак что в этом случае они хранят, вероятно, байт.Чтобы получить бит, о котором они заботятся, они используют битовые операции для манипулирования байтом:

const int OPEN_CLOSE_BIT = 1 << 0;
const int UPPER_LOWER_BIT = 1 << 1;

byte doorByte = getByteFromSomewhere();

if (doorByte & UPPER_LOWER_BIT) {
    // the door is in some state
}
0 голосов
/ 05 февраля 2012

Хотя они говорят, что используют 4 бита, я знаю, что они на самом деле хранят информацию в одном байте (который легко создать, поскольку байт является примитивным типом данных).

Я не верюможно напрямую сохранить один бит, но я подумал, что вы хотели бы знать, что, хотя они заявили, что используют 4 бита, эти биты хранятся в байте.

...