存储单个位

时间:2012-02-05 01:56:25

标签: storage bit

我的问题可能看起来有点业余,但我无法在任何地方找到答案。不久之前,Minecraft的一位开发人员谈到了如何在游戏中存储门(link)。他说他们用4位存储。 2表示方向,1表示上部或下部,1表示打开或关闭。这让我想到你是怎么做到的。您会看到存储一个字节,因为一个ASCII字符是一个字节。但是,你不能只将一些字符写入一个只有一点的文件,因为字符不能只用一个位存储,它们存储为一个字节。我知道有点表示为1或0.然而,将1或0写入文件将为您提供4个字节而不是单个位。那怎么办?

感谢。

5 个答案:

答案 0 :(得分:3)

这很可能是通过组合不同的二进制标志来完成的。为了能够给出清晰的解释,您必须了解数字如何按位表示。基本上,它就像十进制计数一样,唯一不同的是只有两个数字可用。下面是一个例子(二进制表示中的十进制数字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

如果使用按位或运算符组合这两行 - “|” - 如果第1行的位x为1或第2行的位x为1,则输出的位x为1.因此,在我们的示例中,结果将如下所示:

11111111

逐位和运算符(&)检查第1行的位x是否为1且第2行的位x是否为1。 在我们的例子中,这是输出:

00001010

逐位xor(异或)运算符(^)检查是否只有一行的位x为1。 我们的输出看起来像这样:

11110101

基本上Minecraft的开发人员所做的是他们定义了一些标志。

// this is just an example, not Minecraft's actual code

public static final byte ORIENTATION_SOUTH = 0; // 00000000
public static final byte ORIENTATION_NORTH = 1; // 00000001
public static final byte ORIENTATION_WEST = 2;  // 00000010
public static final byte ORIENTATION_EAST = 3;  // 00000011

public static final byte PART_UPPER = 4;        // 00000100 - third bit is 1
public static final byte PART_LOWER = 0;        // 00000000 - third bit is 0

public static final byte STATE_OPEN = 8;        // 00001000 - fourth bit is 1
public static fianl byte STATE_CLOSED = 0;      // 00000000 - fourth bit is 0

因此,如果他们想要一个门的上部朝西并且打开的门状态,他们会这样写:

byte state = ORIENTATION_WEST | PART_UPPER | STATE_OPEN;

按位,它看起来像这样:

00000010 | (orientation)
00000100 | (part)
00001000   (open or closed)

然后最终会:

00001110 (west, upper part, open)

虽然只使用了字节的前4位,但正如你所说,你不能只保存位。很可能整个字节都被保存了。

答案 1 :(得分:2)

你是对的,当你只需要存储一个位时就不能这样做:你必须保存至少一个字节。

但是,如果您有多个项目,每个项目少于一个字节,您可以在一个字节中打包多个项目。

以4位门为例,假设您要存储有关两扇门的信息。你需要8位,这是一个字节。您可以将第一个门保存在较低的四位中,将第二个门保存在较高的四位中。当您需要获取第一个门的状态时,通过应用twoDoorsInOneByte & 0x0F操作来屏蔽第二个门:它会剥离字节的较高部分。当你需要第二扇门时,使用向左移位将其位移动到位:(twoDoorsInOneByte >> 4) & 0x0F:它将高四位移动到高四位,并清除字节上半部分的位以防万一价值得到了扩大。

最后,在C中您还有另一种选择:您可以使用bit fields。当您希望将任意长度的元素打包成几个单词以节省空间时,这可能很有用。请注意,应该谨慎应用此技术,当节省相对较高,或者内存太稀疏时(例如,您正在为8位微控制器编写嵌入式代码)。

答案 2 :(得分:1)

定义:

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)

要在4上设置bkg color 5和fgd,请使用:

color = 5 << 3 | 4 

要获得背景颜色:

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

如果每分钟制作游戏很重要。尽可能避免使用位操作:)

答案 3 :(得分:0)

虽然他们说他们使用了4位,但我知道他们实际上是将信息存储在一个字节中(这很容易创建,因为字节是原始数据类型)。

我不相信可以直接存储一个位,但我想你想知道虽然他们说他们使用4位,但这些位存储在一个字节中。

答案 4 :(得分:0)

几乎所有现代计算机都是字节可寻址的,这意味着你只能寻址(指向)一个字节的内存而不是更小的内存。所以在这种情况下,它们可能存储一个字节。为了得到他们关心的位,他们使用位操作来操作字节:

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
}