存储单个位



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

谢谢。

这很可能是通过组合不同的二进制标志来完成的。为了能够给你一个清晰的解释,你必须了解数字是如何按位表示的。基本上,这就像十进制计数一样,唯一的区别是只有两个数字可用。下面是一个示例(十进制数 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,如果行 1 的位 x 为 1 或行 2 的位 x 为 1。因此,在我们的例子中,结果将如下所示:

11111111
按位和运算符 (&( 检查第 1 行的位 x 是否为 1,

第 2 行的位 x 是否为 1。在我们的例子中,这是输出:

00001010

按位异或(独占或(运算符 (^( 检查是否只有一行的位 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 位,但正如你所说,你不能只保存位。很可能整个字节都被保存了。

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

但是,如果您有多个项目

,每个项目占用的时间少于一个字节,则可以将多个项目打包在一个字节中。

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

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

定义:

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 颜色 5 和 fgd 设置为 4,请使用:

color = 5 << 3 | 4 

要获取背景颜色,请使用:

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

如果你做游戏,每一个nsec都很重要。尽量避免使用位操作,只要有可能:)

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

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

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

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
}

相关内容

  • 没有找到相关文章

最新更新