通过c#中的位掩码存储多个值

我试图通过位掩码在32位int中存储四个独立的5位值(0-31)但是在设置正确的值时遇到问题并从用于存储的掩码int中获取各个值。

谁能帮我这个?

编辑:

对不起外部链接 – 这里有一些JavaScript演示了我想要实现的目标(但是在位掩码而不是十进制代数中):

var s = 0; var v = [31, 6, 23, 31]; //save values s = v[0] + (v[1] * 32) + (v[2] * 1024) + (v[3] * 32768); console.log(s); //retrieve values v[3] = parseInt(s / 32768); v[2] = parseInt((s - (v[3] * 32768)) / 1024); v[1] = parseInt((s - ((v[3] * 32768) + (v[2] * 1024))) / 32); v[0] = parseInt(s - ((v[3] * 32768)+ (v[2] * 1024) + (v[1] * 32))); console.log(v); //modify values [1] and [2] s = s - (v[1] * 32) + (9 * 32); s = s - (v[2] * 1024) + (17 * 1024); console.log(s); //retrieve values v[3] = parseInt(s / 32768); v[2] = parseInt((s - (v[3] * 32768)) / 1024); v[1] = parseInt((s - ((v[3] * 32768) + (v[2] * 1024))) / 32); v[0] = parseInt(s - ((v[3] * 32768)+ (v[2] * 1024) + (v[1] * 32))); console.log(v); 

输出:

 1039583 [31, 6, 23, 31] 1033535 [31, 9, 17, 31] 

编辑:

感谢Peter Duniho,我能够使用内置的掩码制作这些掩码,以便在32位整数内保存6个5位值的操作:

 uint Get_5_In_32(uint storage, int index) { switch (index) { case 0: return (storage & 0x0000001F); case 1: return (storage & 0x000003E0) >> 5; case 2: return (storage & 0x00007C00) >> 10; case 3: return (storage & 0x000F8000) >> 15; case 4: return (storage & 0x01F00000) >> 20; case 5: return (storage & 0x3E000000) >> 25; default: return (0); } } uint Set_5_In_32(uint storage, uint value, int index) { if (value > 31) { value = 31; } switch (index) { case 0: return (storage & 0xFFFFFFE0) | value; case 1: return (storage & 0xFFFFFC1F) | (value << 5); case 2: return (storage & 0xFFFF83FF) | (value << 10); case 3: return (storage & 0xFFF07FFF) | (value << 15); case 4: return (storage & 0xFE0FFFFF) | (value << 20); case 5: return (storage & 0xC1FFFFFF) | (value << 25); default: return (0); } } 

还有一个byref版本的Set函数,用于更少的分配:

 void Set_5_In_32(ref uint storage, uint value, int index) { if (value > 31) { value = 31; } switch (index) { case 0: storage &= 0xFFFFFFE0; storage |= value; break; case 1: storage &= 0xFFFFFC1F; storage |= (value << 5); break; case 2: storage &= 0xFFFF83FF; storage |= (value << 10); break; case 3: storage &= 0xFFF07FFF; storage |= (value << 15); break; case 4: storage &= 0xFE0FFFFF; storage |= (value << 20); break; case 5: storage &= 0xC1FFFFFF; storage |= (value << 25); break; } } 

如果没有更具体的问题,特别是你展示了迄今为止的代码并解释了你在实现它时遇到的麻烦,很难确切地知道最佳答案是什么。

也就是说,这里有几个示例方法可能会让您指向正确的方向:

 // Stores the given value in storage at the given index int Set(int storage, int value, int index) { int shiftCount = index * 5, mask = 0x1f << shiftCount; return (storage & ~mask) | (value << shiftCount); } // Retrieves the value stored in storage at the given index int Get(int storage, int index) { int shiftCount = index * 5, mask = 0x1f << shiftCount; return (storage & mask) >> shiftCount; } 

上面的Set()方法获取storage的当前值,清除要存储五位值的位范围内的所有位,然后使用| 运算符来存储该五位值,首先将该值的位移到正确的位置。

Get()方法执行反向操作。 它屏蔽掉(清除) 不在存储值的位范围内的所有位,然后在返回结果之前将存储的位向下移位到int的最低有效位。

笔记:

  • 以上内容针对您陈述的问题。 通过封装在可以在初始化时配置位计数的类并且基于该位计数生成掩码而不是硬编码,可以很容易地推广它。
  • 上面的代码中没有错误检查。 在生产代码版本中,validation传递给Set()方法的value实际上是否适合五位(即小于0x20 )会更好。

编辑:

这是一个简单的控制台程序,它使用您的示例数据演示上述内容的使用:

 static void Main(string[] args) { int[] array = { 31, 6, 23, 31 }; int storage = 0; storage = ArrayToStorage(array, storage); Console.WriteLine(storage); LogArray(array); storage = Set(storage, 9, 1); storage = Set(storage, 17, 2); StorageToArray(array, storage); Console.WriteLine(storage); LogArray(array); } static int ArrayToStorage(int[] array, int storage) { for (int i = 0; i < array.Length; i++) { storage = Set(storage, array[i], i); } return storage; } static void StorageToArray(int[] array, int storage) { for (int i = 0; i < array.Length; i++) { array[i] = Get(storage, i); } } static void LogArray(int[] array) { Console.WriteLine("[" + string.Join(", ", array) + "]"); } // Stores the given value in storage at the given index static int Set(int storage, int value, int index) { int shiftCount = index * 5, mask = 0x1f << shiftCount; return (storage & ~mask) | (value << shiftCount); } // Retrieves the value stored in storage at the given index static int Get(int storage, int index) { int shiftCount = index * 5, mask = 0x1f << shiftCount; return (storage & mask) >> shiftCount; }