【问题标题】:Jumping segments in binary二进制跳转段
【发布时间】:2013-06-09 08:20:07
【问题描述】:

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

例如,如果您有 10011 并从第一位(最右边)开始并搜索第一个 0,那么它将是从右到左的第三位。如果您随后从第 3 位开始并想找到下一个 1,它将位于第 5 位(最左侧)。

感谢您的帮助,如果我需要进一步提供任何信息,请随时告诉我。

编辑:这是我当前的代码。

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

【问题讨论】:

  • @STLDeveloper 只有各种形式的迭代。我开始只是移位,直到最右边的位发生变化,然后记录移位次数,直到位位置 0 发生变化。如果我需要指定一个“起始”位置,我会在运行循环之前移动该数量。由于它都是二进制的,我希望有一个更优雅的选择。
  • 你对结果做了什么?有可能直接使用指示该位的掩码完成的事情,还是真的必须是索引?
  • @harold 我想我应该更愿意提供信息来获取信息。我正在研究一种进行多维洪水填充的方法,以识别游戏标量场/体素地形环境中的所有实体对象。我相信通过一些类似的技巧,我可以获得比典型的迭代方法洪水填充更好的结果。
  • 我将把我的 3D 地形数据存储在页面/块中,每个 Y 坐标都有一个字节值(X/Z 是水平的)。如果我能以“游程编码”的方式遍历字节值,从我的角度来看,这听起来像是一种巧妙的方法。
  • 好吧,你可以跳过“起始位置”-shift,方法是使用掩码设置/取消设置你找到的位。此外,对于按位技巧,使用更宽的词几乎总是更好,因为它减少了开销。我还不确定你在做什么

标签: c# binary bit-manipulation bit-shift


【解决方案1】:

有一些方法,但它们很丑,因为没有 _BitScanForward 或等效的内在函数。尽管如此,您实际上可以有效地计算这个东西,而不需要一个巨大的表。

第一步:创建一个数字,在您要搜索的位置为 1,其他位置为 0。

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

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

【讨论】:

  • 我不得不问,出于性能原因,访问 2D 锯齿状数组不会比您提供的选项更快(考虑到我仍然需要日志函数或查找表的可能性更大)?肯定没有那么优雅,但性能确实是我的主要意图。
  • 可能不是,这意味着取消引用两个依赖指针(如果它们在 L1 中还不错,否则很糟糕),而您可以使用强制转换为 double 并重新解释位来计算日志。如果您要使用表格,请将其设为一维数组并进行一些数学运算以获取索引(并使用unsafe 访问)。如果有更大的字长是有意义的,那应该只与掩码/位扫描选项结合使用,表会变得太大(它们可能适合内存,但最后一级缓存未命中需要大约一百周期)
【解决方案2】:

使用查找表。也就是说,预先计算一个以字节值和当前位置为索引的二维数组。您可以为 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 设置一个“下一个”。

【讨论】:

    猜你喜欢
    • 2012-10-26
    • 2014-10-30
    • 1970-01-01
    • 2013-02-02
    • 2021-07-29
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多