首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将范围转换为位数组

将范围转换为位数组
EN

Stack Overflow用户
提问于 2009-03-27 02:29:30
回答 6查看 2.4K关注 0票数 0

我正在用C#编写一段时间关键型代码,它要求我将定义包含范围的两个无符号整数转换为位字段。例如:

代码语言:javascript
运行
复制
uint x1 = 3;
uint x2 = 9;
  //defines the range [3-9]
  //                              98  7654 3
  //must be converted to:  0000 0011  1111 1000

这可能有助于以相反的顺序可视化这些位

这个范围的最大值是在运行时给出的一个参数,我们称之为max_val。因此,位字段变量应该定义为大小等于max_val/32UInt32数组

代码语言:javascript
运行
复制
UInt32 MAX_DIV_32 = max_val / 32;
UInt32[] bitArray = new UInt32[MAX_DIV_32];

给定由变量x1x2定义的范围,执行此转换的最快方法是什么?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-03-27 03:58:23

尝尝这个。计算必须用全1填充的数组项的范围,并通过迭代此范围来执行此操作。最后,在两个边框上设置项。

代码语言:javascript
运行
复制
Int32 startIndex = x1 >> 5;
Int32 endIndex = x2 >> 5;

bitArray[startIndex] = UInt32.MaxValue << (x1 & 31);

for (Int32 i = startIndex + 1; i <= endIndex; i++)
{
   bitArray[i] = UInt32.MaxValue;
}

bitArray[endIndex] &= UInt32.MaxValue >> (31 - (x2 & 31));

可能代码不是100%正确的,但是这个想法应该是可行的。

我刚测试了一下,发现了三个bug。开始索引处的计算需要mod 32,结束索引处的32必须是31,并且是逻辑and而不是赋值,以处理开始索引和结束索引相同的情况。应该是相当快的。

我刚刚对它进行了基准测试,将x1和x2均匀分布在阵列上。Windows XP主机上的英特尔酷睿2双核E8400 3.0 GHz、MS VirtualPC和E8400 2003 R2。

代码语言:javascript
运行
复制
Array length [bits]           320         160         64
Performance [executions/s]    33 million  43 million  54 million

再优化一次x% 32 == x& 31,但我无法保证性能提升。因为在我的测试中只有10.000.000次迭代,所以波动非常大。而且我在VirtualPC中运行,这使得情况变得更加不可预测。

票数 2
EN

Stack Overflow用户

发布于 2013-01-16 17:23:38

我的解决方案是将BitArray中的所有位设置为true或false:

代码语言:javascript
运行
复制
public static BitArray SetRange(BitArray bitArray, Int32 offset, Int32 length, Boolean value)
{

    Int32[] ints = new Int32[(bitArray.Count >> 5) + 1];

    bitArray.CopyTo(ints, 0);

    var firstInt = offset >> 5;
    var lastInt = (offset + length) >> 5;

    Int32 mask = 0;

    if (value)
    {
        // set first and last int
        mask = (-1 << (offset & 31));
        if (lastInt != firstInt)
            ints[lastInt] |= ~(-1 << ((offset + length) & 31));
        else
            mask &= ~(-1 << ((offset + length) & 31));

        ints[firstInt] |= mask;

        // set all ints in between
        for (Int32 i = firstInt + 1; i < lastInt; i++)
            ints[i] = -1;
    }

    else
    {
        // set first and last int
        mask = ~(-1 << (offset & 31));
        if (lastInt != firstInt)
            ints[lastInt] &= -1 << ((offset + length) & 31);
        else
            mask |= -1 << ((offset + length) & 31);

        ints[firstInt] &= mask;

        // set all ints in between
        for (Int32 i = firstInt + 1; i < lastInt; i++)
            ints[i] = 0;

    }

    return new BitArray(ints) { Length = bitArray.Length };

}
票数 2
EN

Stack Overflow用户

发布于 2009-03-27 02:43:48

您可以尝试:

代码语言:javascript
运行
复制
UInt32 x1 = 3;
UInt32 x2 = 9;
UInt32 newInteger = (UInt32)(Math.Pow(2, x2 + 1) - 1) & 
                   ~(UInt32)(Math.Pow(2, x1)-1);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/688314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档