C# 二进制跳转段

C# 二进制跳转段,c#,binary,bit-manipulation,bit-shift,C#,Binary,Bit Manipulation,Bit Shift,我的问题是,在C#中,有没有一种方法可以在一个字节中找到下一个二进制数字,该字节的指定值为0或1,而无需迭代(寻找最高的性能选项) 例如,如果您有10011,从第一位(最右边)开始搜索第一个0,它将是从右向左的第三位。如果你从第三位开始,想要找到下一个1,那么它将位于第五位(最左边) 谢谢你的帮助,如果需要进一步的帮助,请随时告诉我 编辑:这是我当前的代码 private int GetBinarySegment(uint uiValue, int iStart, int iMaxBits, b

我的问题是,在C#中,有没有一种方法可以在一个字节中找到下一个二进制数字,该字节的指定值为0或1,而无需迭代(寻找最高的性能选项)

例如,如果您有10011,从第一位(最右边)开始搜索第一个0,它将是从右向左的第三位。如果你从第三位开始,想要找到下一个1,那么它将位于第五位(最左边)

谢谢你的帮助,如果需要进一步的帮助,请随时告诉我

编辑:这是我当前的代码

private int GetBinarySegment(uint uiValue, int iStart, int iMaxBits, byte bValue)
{
    int r = 0; uiValue >>= iStart; 
    if (uiValue == 0) return iMaxBits - iStart;
    while ((uiValue & 1) == bValue) { uiValue >>= 1; r++; }
    return r;
}

使用查找表。也就是说,预先计算按字节值和当前位置索引的2D数组。您可以为0和1创建单独的表格,也可以将其合并

例如,从数字19的第0位开始。这正好是1。因此,如果您查找
nextBit[19][0]
,它应该返回
1
,依此类推。下面是组合查找表的外观。它显示0和1的下一位:

nextBit[19][0] = 1   // 1
nextBit[19][1] = 4   // 1
nextBit[19][2] = 3   // 0
nextBit[19][3] = 4   // 0
nextBit[19][4] = 0   // 1
nextBit[19][5] = 6   // 0
nextBit[19][6] = 7   // 0
显然,第7位没有“下一个”,如果“下一个”返回0,则该特定位不再存在


我可能错误地解释了你的问题,但这项技术可以根据你的目的进行修改。我最初认为您希望浏览所有1位或0位。如果您想跳过连续的1位,那么您只需以这种方式排列表。或者实际上,您可以在每个位置为0和1都设置一个“下一步”。

有很多方法,但它们都很难看,因为没有
\u BitScanForward
或等效的内在函数。尽管如此,您实际上可以高效地计算这件事,而不需要庞大的表

第一步:在你要搜索的位置打一个1,在其他地方打一个0

如果搜索1,则表示
x&-x
。如果搜索0,请使用
~x&(x+1)


然后,使用多种方法中的一种来模拟任意一个位扫描(现在只有一个设置位,所以从哪一侧搜索并不重要)。有些方法很详细(不是用C#,但是你可以转换它们)。

@STLDeveloper只支持各种形式的迭代。我一开始只是移位,直到最右边的位发生变化,然后记录移位的次数,直到位位置0发生变化。如果我需要指定一个“起始”位置,我会在运行循环之前转移该数量。由于它都是二进制的,我希望有一个更优雅的选择。你对结果做了什么?一些有可能直接用一个表示该位的掩码来完成的事情,或者它真的必须是一个索引吗?@harold我想为了获得信息,我应该更愿意给出它。我当时正在研究一种方法,即在一个标量场/体素地形环境中进行多维泛洪填充,以识别游戏中的所有实体对象。我相信通过一些类似的技巧,我可以获得比典型迭代方法flood fill更好的结果性能。我将以页/块的形式存储我的3D地形数据,每个Y坐标的字节值(X/Z是水平的)。如果我能以“运行长度编码”的方式遍历字节值,从我的角度来看,这听起来是一种很好的方法。好吧,首先,你可以跳过“起始位置”——通过使用掩码设置/取消设置你找到的位。此外,使用更宽的字几乎总是更好的按位技巧,因为它减少了开销。我还不确定您在做什么,但出于性能原因,我不得不问,访问2D锯齿阵列是否会比您提供的选项更快(考虑到我仍然很可能需要一个日志函数或查找表)?当然没有那么优雅,但性能确实是我的主要目的。可能不是,这意味着取消引用两个相关指针(如果它们在L1中,则不太糟糕,但在其他情况下则很糟糕),而您可以使用转换为双精度的方法计算日志并重新解释位。如果要使用表,请将其设置为1D数组和一些数学运算来获取索引(并使用
safe
access)。如果有一个更大的字大小是有意义的,这应该只与掩码/位扫描选项相结合,那么表就会变得太大(它们可能适合内存,但最后一级缓存未命中的时间大约为100个周期)