【发布时间】:2009-01-15 05:20:26
【问题描述】:
我正在做一个需要在字节级别处理整数的项目。由于节省空间是首要考虑因素,因此我只需要非常小的(和可变长度的整数)。
有没有办法可以将 int '4096' 转换为 3 个字节?还是 '1053' 变成 2 个字节?
显然我可以手动执行 = (byte[0] * 256) + (byte[1]),但我想知道是否有更简单的选项可以将 int 转换为 x 字节并再次返回?
【问题讨论】:
我正在做一个需要在字节级别处理整数的项目。由于节省空间是首要考虑因素,因此我只需要非常小的(和可变长度的整数)。
有没有办法可以将 int '4096' 转换为 3 个字节?还是 '1053' 变成 2 个字节?
显然我可以手动执行 = (byte[0] * 256) + (byte[1]),但我想知道是否有更简单的选项可以将 int 转换为 x 字节并再次返回?
【问题讨论】:
您可以进行可变长度整数编码。多年前的旧方法是使用每个字节的高位来表示整数继续到另一个字节。所以你每字节丢失一位,但获得小整数。这在每个最后一个字节都很重要的持久存储中非常有用。
示例:假设我们正在处理无符号整数,我们将有
int binary
0 00000000
1 00000001
...
127 01111111
128 00000001 10000000
129 00000001 10000001
...
255 00000001 11111111
256 00000010 10000000
...
16383 01111111 11111111
16384 00000001 10000000 10000000
所以 0-127 占用 1 个字节,128-16383 占用 2 个字节,依此类推...
如需更复杂的方法,请查看this page
【讨论】:
为了更加疯狂,让我们在 C# 中使用旧的 C 风格联合技巧:
[StructLayout(LayoutKind.Explicit)]
struct OddUnion
{
/* The 32-bit integer value */
[FieldOffset(0)]
public int IntegerValue;
/* The bytes that overlap with it */
[FieldOffset(0)]
public byte Byte1;
[FieldOffset(1)]
public byte Byte2;
[FieldOffset(2)]
public byte Byte3;
[FieldOffset(3)]
public byte Byte4;
}
然后,当您想“转换”时,请执行以下操作:
OddUnion myOddUnion;
myOddUnion.IntegerValue = 4096;
Byte secondByte = myOddUnion.Byte1;
但这只有在您希望“节省”从字中移出单个字节的成本时才真正有帮助。我没有查看生成的 SMIL,所以我不知道这与任何其他解决方案相比是否便宜。
【讨论】:
你可以吗?当然。它会节省任何空间吗?也许,取决于你想做多少工作。您必须了解处理器是 32 位的,这意味着它有 4 个字节的寄存器,这就是它想要存储和访问事物的方式。要强制使用 3 字节“int”,您必须将其保存在字节数组中,并在使用前将其从数组中提取到对齐的地址。这意味着,如果您将其存储得很短,编译器要么将其填充(并且您将失去任何您认为已创建的效率),要么它的读写速度会很多慢。
如果这是一款桌面应用程序,那么节省空间究竟是如何成为首要考虑因素的,尤其是在每个元素占用 1 个字节时?元素访问的性能损失可能会改变您对一个字节的重要性的看法。
我认为如果那 1 个字节真的很重要,那也许,只是也许,你使用了错误的语言。如果我一开始不安装和使用 CLR,您将节省的字节数是这些字节中的 lot。
旁注:您还可以进行移位,而不是乘法(尽管编译器可能会为您提供)。
【讨论】:
BitConverter.GetBytes 将为您获取字节。
和
BitConverter.ToInt32 将从字节中获取 32 位 int。
【讨论】:
你必须做一些位移。使用 HEX 会更容易,因为每个数字(我的意思是每个数字,但数字是基数 10,hexgit)代表四个位。
【讨论】: