如何将 8 个 4 位值编码为 Int32,然后取回这些值?
How to encode 8 4bit values into an Int32 and then get those back?
如何将 8 个 4 位(如果您喜欢十六进制,则为 0..15 或 0..F ;))值放入 C# 中的 Int32 (int) 并取回这些值?我需要这些用于我正在编写的游戏,或者更具体地说,它的编辑器(它将具有像 Notch 失败的 0x10c 中那样的顶点操作),并且由于已经有一些遗留代码和构建的关卡很少,我真的不能破坏格式所以我可以使用 Int64 并使用 BitConverter class ;).
编码 8 个 8 位值
我不太擅长按位运算,到目前为止,那些试图向我解释这些的人都失败了,是的。需要帮助。
主要思想是使用左<<
移位和|
来编码和&
和右>>
移位解码。假设值被组织为数组:
byte[] data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int result = data
.Select((value, i) => value << (4 * i))
.Aggregate((x, y) => x | y); // or just .Sum() - Jeppe Stig Nielsen's idea
编辑: for 循环 实现:
int result = 0;
for (int i = 0; i < data.Length; ++i)
result |= data[i] << (4 * i);
检索第index
个值(index
在[0..7]
范围内)
byte item = (byte) ((result >> (index * 4)) & 0xF);
如果不想考虑按位运算,可以设置一个BitVector32,像这样:
var bv = new BitVector32();
var sections = new BitVector32.Section[8];
// Create 8 4-bit sections
sections[0] = BitVector32.CreateSection(15);
for (var i = 1; i < 8; ++i)
{
sections[i] = BitVector32.CreateSection(15, sections[i - 1]);
}
// Initialize the sections. Values will be 0F, 0D, 0B, ... ,01
for (var i = 0; i < 8; ++i)
{
bv[sections[i]] = 15 - i*2;
}
// and output results
for (var i = 0; i < 8; ++i)
{
Console.WriteLine("{0,2}: {1:X2}", i, bv[sections[i]]);
}
Console.WriteLine("bv value = {0:X4}", bv.Data);
评论后
"conciseness" 和性能的问题比评论所暗示的要复杂得多。在一个工作程序中,这段代码中设置部分的部分可以在程序启动时完成一次。例如:
BitVector32.Section value1 = BitVector32.CreateSection(15);
BitVector32.Section value2 = BitVector32.CreateSection(15, value1);
BitVector32.Section value3 = BitVector32.CreateSection(15, value2);
// set up others here
然后,当您想要访问单个值时:
BitVector32 bv = new BitVector32(someValue);
// get one value
int myValue = bv[value2];
// set one value
bv[value3] = 42;
比
更简洁
int myValue = (someValue >> 4) & 0x0f;
someValue = (someValue & 0xfffff0ff) | (42 << 8);
性能是一个悬而未决的问题。 JIT 编译器很可能可以为这些部分操作生成内联代码。
如何将 8 个 4 位(如果您喜欢十六进制,则为 0..15 或 0..F ;))值放入 C# 中的 Int32 (int) 并取回这些值?我需要这些用于我正在编写的游戏,或者更具体地说,它的编辑器(它将具有像 Notch 失败的 0x10c 中那样的顶点操作),并且由于已经有一些遗留代码和构建的关卡很少,我真的不能破坏格式所以我可以使用 Int64 并使用 BitConverter class ;).
编码 8 个 8 位值我不太擅长按位运算,到目前为止,那些试图向我解释这些的人都失败了,是的。需要帮助。
主要思想是使用左<<
移位和|
来编码和&
和右>>
移位解码。假设值被组织为数组:
byte[] data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int result = data
.Select((value, i) => value << (4 * i))
.Aggregate((x, y) => x | y); // or just .Sum() - Jeppe Stig Nielsen's idea
编辑: for 循环 实现:
int result = 0;
for (int i = 0; i < data.Length; ++i)
result |= data[i] << (4 * i);
检索第index
个值(index
在[0..7]
范围内)
byte item = (byte) ((result >> (index * 4)) & 0xF);
如果不想考虑按位运算,可以设置一个BitVector32,像这样:
var bv = new BitVector32();
var sections = new BitVector32.Section[8];
// Create 8 4-bit sections
sections[0] = BitVector32.CreateSection(15);
for (var i = 1; i < 8; ++i)
{
sections[i] = BitVector32.CreateSection(15, sections[i - 1]);
}
// Initialize the sections. Values will be 0F, 0D, 0B, ... ,01
for (var i = 0; i < 8; ++i)
{
bv[sections[i]] = 15 - i*2;
}
// and output results
for (var i = 0; i < 8; ++i)
{
Console.WriteLine("{0,2}: {1:X2}", i, bv[sections[i]]);
}
Console.WriteLine("bv value = {0:X4}", bv.Data);
评论后
"conciseness" 和性能的问题比评论所暗示的要复杂得多。在一个工作程序中,这段代码中设置部分的部分可以在程序启动时完成一次。例如:
BitVector32.Section value1 = BitVector32.CreateSection(15);
BitVector32.Section value2 = BitVector32.CreateSection(15, value1);
BitVector32.Section value3 = BitVector32.CreateSection(15, value2);
// set up others here
然后,当您想要访问单个值时:
BitVector32 bv = new BitVector32(someValue);
// get one value
int myValue = bv[value2];
// set one value
bv[value3] = 42;
比
更简洁int myValue = (someValue >> 4) & 0x0f;
someValue = (someValue & 0xfffff0ff) | (42 << 8);
性能是一个悬而未决的问题。 JIT 编译器很可能可以为这些部分操作生成内联代码。