【问题标题】:Interpreting a std::vector<unsigned int> as bitvector - efficient algorithm?将 std::vector<unsigned int> 解释为位向量 - 高效算法?
【发布时间】:2015-10-16 17:34:03
【问题描述】:

我想解释

std::vector<unsigned int> numbers

作为位向量,即numbers[0]的MSB是第1位,numbers[1]的MSB是第33位,以此类推。我想在这个向量中找到 Ones 的所有序列,并将相应的位置存储在数据结构中。 (这里也将单个 One 定义为序列)

例如:我将值 15 和 112 存储在数字中。因此位 29 到 32 和位 58 到 60 等于 1。 挑战是优化这个函数的运行时间。

这是我如何处理这个问题的想法:我想到了使用两个 for 循环。第一个循环遍历“数字”的元素(我们称之为 element_loop),而第二个循环用于计算单个元素中所有 One 的位置(我们称之为 bit_loop)。为此,我想到了检测序列的“上升沿”和“下降沿”。

在每个 bit_loop 循环开始时,掩码被初始化为十六进制。值0x80000000。使用此掩码,我检查第 1 位是否等于 1。如果是,则存储当前位置 (0)。接下来,使用二进制表示“1000...”的掩码来检测下一个周期中的“下降沿”。如果否,则将掩码向右移动一位“0100...”,以便在下一个周期中检测“上升沿”。 (我只关心这两个粗体数字)

一旦检测到边缘,我会存储当前位置并以适当的方式将掩码移动一位。因此,在 pos 之后。 edge (01) 我切换到 neg。边缘检测(10),反之亦然。在遍历 32 位无符号数时,我将所有边缘位置存储在某种向量中。这个向量可以是 2-dim。数组,第一列是一个序列的开始,第二列是序列的结束。此外,我需要对从一个元素到下一个元素的转换进行一些特殊处理。

这是我的一般性问题:您如何看待这种方法?有没有办法更有效地处理这个问题?非常感谢您提前提供的帮助。

【问题讨论】:

  • 如果您想确保它是 32 位并同时隐含记录该事实,请使用 uint32_t
  • 嗯,你可以试试 std::vector 或 bitset
  • 检查this如何检查是否设置了单个位的答案。
  • 我只能为 Surt 的评论点赞一次。对不起@Surt
  • 如何让 MSB 为 1 位???你有大端处理器还是使用网络字节序?

标签: c++ algorithm bitvector


【解决方案1】:

有多种位技巧可以有效地进行位扫描,但如果您使用 C++,则可以利用 std::bitsetboost::dynamic_bitset 来迭代位位置。不过,您描述的算法会为每个块向后迭代,因此您可能希望使用 32 - (32 - i) 之类的东西来反转您的位置。

根据体系结构,每个位应该大约需要一个周期。

【讨论】:

    【解决方案2】:

    使用特殊的处理器指令或各种巧妙的技巧(参见例如Position of least significant bit that is set),有一些有效的(恒定时间)方法可以找到一个字中的第一位集。

    稍加小心,您可以向后工作并使用它们来扫描第一个,然后进行一些掩码和位翻转并搜索下一个零,等等。

    可能给你一个更快的算法,特别是如果序列平均很长,所以快速扫描的收益超过了比特旋转的成本。

    【讨论】:

    • 非常感谢您的提示!这就是我现在正在使用的:从 LSB 端开始,我用 DeBruijn 序列检测到第一个“1”。之后,我反转数字并使用掩码(0xFFFFFFFF
    猜你喜欢
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多