通过掩码在C#中存储多个值 [英] Storing multiple values via bitmask in c#

查看:288
本文介绍了通过掩码在C#中存储多个值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过存储位掩码32位int内的四个独立的5位值(0-31),但我有麻烦的正确值来设置,并从蒙面INT多用于获取单个值。存储



谁能帮我这个



编辑:



很抱歉的外部链接 - 这里的一些JavaScript证明什么,我试图实现(但在位屏蔽,而不是小数代数):

 变种S = 0; 

变种V = [31,6,23,31];

//保存值
S = v [0] +(V [1] * 32)+(V [2] * 1024)+(V [3] * 32768);

的console.log(S);

//检索值
)(V [3] = parseInt函数(秒/ 32768);
)(V [2] = parseInt函数((S - (ⅴ[3] * 32768))/ 1024);
)(V [1] = parseInt函数((S - ((ⅴ[3] * 32768)+(ⅴ[2] * 1024)))/ 32);
)(V [0] = parseInt函数(S - ((ⅴ[3] * 32768)+(ⅴ[2] * 1024)+(V [1] * 32)));

的console.log(V);

//修改值[1]和[2]
S =秒 - (ⅴ[1] * 32)+(9 * 32);
S = S - (V [2] * 1024)+(17 * 1024);

的console.log(S);

//检索值
)(V [3] = parseInt函数(秒/ 32768);
)(V [2] = parseInt函数((S - (ⅴ[3] * 32768))/ 1024);
)(V [1] = parseInt函数((S - ((ⅴ[3] * 32768)+(ⅴ[2] * 1024)))/ 32);
)(V [0] = parseInt函数(S - ((ⅴ[3] * 32768)+(ⅴ[2] * 1024)+(V [1] * 32)));

的console.log(V);



输出:

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

编辑:



感谢彼得Duniho我能够让这些用口罩建立保存

  UINT Get_5_In_32(UINT存储,INT指数)$ b:32位整数里面6 5位值一些操作$ b {
开关(指数)
{
的情况下0:
回报(存储&安培; 0x0000001F);
案例1:
回报(存储&安培; 0x000003E0)GT;> 5;
案例2:
回报(存储&安培; 0x00007C00)GT;> 10;
案例3:
回报(存储&安培; 0x000F8000)GT;> 15;
案例4:
回报(存储&安培; 0x01F00000)GT;> 20;
案例5:
回报(存储&安培; 0x3E000000)GT;> 25;
默认:
回报(0);
}
}
UINT Set_5_In_32(UINT存储,UINT值,INT指数)
{
如果(价值> 31){值= 31; }
开关(指数)
{
的情况下0:
回报(存储&安培; 0xFFFFFFE0)|值;
案例1:
回报(存储&安培; 0xFFFFFC1F)| (值下;小于5);
案例2:
回报(存储&安培; 0xFFFF83FF)| (值下;小于10);
案例3:
回报(存储&安培; 0xFFF07FFF)| (价值<< 15);
案例4:
回报(存储&安培; 0xFE0FFFFF)| (价值<< 20);
案例5:
回报(存储&安培; 0xC1FFFFFF)| (价值<< 25);
默认:
回报(0);
}
}

和设置功能,即使少了按地址版本配置:

 无效Set_5_In_32(REF UINT存储,UINT值,INT指数)
{
如果(值> 31){值= 31; }
开关(指数)
{
的情况下0:
储存与放大器; = 0xFFFFFFE0;
存储| =价值;
中断;
案例1:
储存与放大器; = 0xFFFFFC1F;
存储| =(价值<< 5);
中断;
案例2:
储存与放大器; = 0xFFFF83FF;
存储| =(价值<< 10);
中断;
案例3:
储存与放大器; = 0xFFF07FFF;
存储| =(价值<< 15);
中断;
案例4:
储存与放大器; = 0xFE0FFFFF;
存储| =(价值<< 20);
中断;
案例5:
储存与放大器; = 0xC1FFFFFF;
存储| =(价值<< 25);
中断;
}
}


解决方案

无一个更具体的问题,特别是你展示你的代码迄今并解释您遇到问题的专门的在得到它的工作而言,这是很难确切地知道什么是最好的答案会是什么。是



这是说,这里有几个例子方法,可能让你在正确的方向:

  //存储在存储在给定的索引
INT设置给定值(INT存储,int值,诠释指数)
{
INT shiftCount转换=指数* 5,
掩码= 0x1F的<< shiftCount转换;

回报(存储&安培;〜面罩)| (价值<< shiftCount转换);
}

//获取在给定的索引
INT获取(int型存储,INT指数)
{
INT shiftCount转换=存储在存储器中的价值指数* 5,
掩码= 0x1F的<< shiftCount转换;

回报(存储&安培;面膜)GT;> shiftCount转换;
}



设置()上述方法发生在存储,清除所有在你要存储五位值,位的范围内位的当前值,然后使用 | 运算符来存储五位值,转移该值对地方第一的位



获取()方法执行相反的操作。它掩盖掉(清除)的所有位的其中值被储存,然后所存储的比特移位至一个 INT



注:




  • 以上是特定于既定的问题。它可以很容易地通过在将位计数可以在初始化被构造和掩模是基于位计数生成而不是硬编码的一类包封一概而论。

  • 毫无错误检查在上面的代码。在生产代码的版本,这将是更好的验证值传递给设置()是否确实符合下列五个比特(即小于 0x20的)。



修改



下面是一个演示使用上面的,你的榜样数据的简单控制台程序:

 静态无效的主要(字串[] args)
{
INT []数组= {31,6,23,31} ;
int型存储= 0;

存储= ArrayToStorage(阵列存储);

Console.WriteLine(储存);
LogArray(数组);

存储=设定(存储,9,1);
=存储组(存储,17,2);

StorageToArray(阵列存储);

Console.WriteLine(储存);
LogArray(数组);
}

静态INT ArrayToStorage(INT []数组,int型存储)
{
的for(int i = 0; I< array.Length;我++)
{
=存储组(存储阵列[我],I);
}

返回存储;
}

静态无效StorageToArray(INT []数组,int型存储)
{
的for(int i = 0; I< array.Length;我++)
{
数组[我] =获取(存储,I);
}
}

静态无效LogArray(INT []数组),
{
Console.WriteLine([+的string.join( 阵列)+]);
}

//卖场在给定的索引
静态INT集(int型存储,int值,诠释指数)
存储给定值{
INT shiftCount转换=指数* 5,
掩码= 0x1F的<< shiftCount转换;

回报(存储&安培;〜面罩)| (价值<< shiftCount转换);
}

//获取在给定的索引
静态INT获取(int型存储,INT指数)
{
INT shiftCount转换存储在存储器中的价值=指数* 5,
掩码= 0x1F的<< shiftCount转换;

回报(存储&安培;面膜)GT;> shiftCount转换;
}


I'm trying to store four independent 5-bit values (0-31) inside a 32-bit int via bit mask but am having trouble getting the values correct to set and get the individual values from the masked int used for storage.

Can anyone help me with this?

Edit:

Sorry for the external link - here's some JavaScript demonstrating what I'm trying to achieve (but in bitmasks instead of decimal algebra):

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);

Output:

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

Edit:

Thanks to Peter Duniho I was able to make these with the masks build in to save some operations for 6 5-bit values inside a 32-bit integer:

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);
    }
}

And a byref version of the Set function for even less allocation:

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;
    }
}

解决方案

Without a more specific question, and in particular you showing the code you have so far and explaining what you're having trouble specifically in terms of getting it to work, it's hard to know exactly what the best answer would be.

That said, here are a couple of example methods that might get you pointed in the right direction:

// 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;
}

The Set() method above takes the current value in storage, clears all of the bits in the range of bits where you want to store your five-bit value, and then uses the | operator to store that five-bit value, shifting the bits of that value to the right place first.

The Get() method performs the reverse operation. It masks off (clears) all of the bits not in the range of bits where the value was stored, and then shifting the stored bits down to the least-significant five bits of an int before returning that result.

Notes:

  • The above is specific to your stated problem. It could easily be generalized by encapsulating in a class where the bit count can be configured at initialization and the mask is generated based on that bit count rather than being hard-coded.
  • There is no error-checking in the above code. In a production-code version, it would be much better to verify that the value passed to the Set() method does in fact fit in five bits (i.e. is less than 0x20).

EDIT:

Here is a simple console program that demonstrates the use of the above, with your example data:

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;
}

这篇关于通过掩码在C#中存储多个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆