我正在用C#编写一段时间关键型代码,它要求我将定义包含范围的两个无符号整数转换为位字段。例如:
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/32的UInt32数组
UInt32 MAX_DIV_32 = max_val / 32;
UInt32[] bitArray = new UInt32[MAX_DIV_32];给定由变量x1和x2定义的范围,执行此转换的最快方法是什么?
发布于 2009-03-27 03:58:23
尝尝这个。计算必须用全1填充的数组项的范围,并通过迭代此范围来执行此操作。最后,在两个边框上设置项。
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。
Array length [bits] 320 160 64
Performance [executions/s] 33 million 43 million 54 million再优化一次x% 32 == x& 31,但我无法保证性能提升。因为在我的测试中只有10.000.000次迭代,所以波动非常大。而且我在VirtualPC中运行,这使得情况变得更加不可预测。
发布于 2013-01-16 17:23:38
我的解决方案是将BitArray中的所有位设置为true或false:
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 };
}发布于 2009-03-27 02:43:48
您可以尝试:
UInt32 x1 = 3;
UInt32 x2 = 9;
UInt32 newInteger = (UInt32)(Math.Pow(2, x2 + 1) - 1) &
~(UInt32)(Math.Pow(2, x1)-1);https://stackoverflow.com/questions/688314
复制相似问题