我想解释
std::vector<unsigned int> numbers
作为位向量,即numbers[0]
的MSB是第1位,numbers[1]
的MSB是第33位,依此类推。我想在此向量中找到 Ones 的所有序列,并将相应的位置存储在数据结构中。 (此处还有一个 One 定义为序列)
例如:我将值15和112存储在数字中。因此,位29至32和位58至60等于1。 挑战是优化此功能的运行时间。
以下是我如何处理这个问题的想法:我想过使用两个 for -loops。第一个循环遍历&#34;数字&#34;的元素。 (让我们称之为element_loop),而第二个循环用于计算单个元素中所有Ones的位置(让我们称之为bit_loop)。我想到了检测&#34;上升&#34;和#34;下降边缘&#34;为此目的的序列
在每个bit_loop循环开始时,掩码初始化为十六进制。价值0x80000000
。使用此掩码,我检查第1位是否等于1。如果是,则存储当前位置(0)。接着,二进制表示掩码&#34; 10 00 ...&#34;用于检测&#34;下降沿&#34;在下一个周期。如果不是,则掩码向右移动一位&#34; 01 00 ...&#34;为了检测上升边缘&#34;在下一个周期。 (我只关心这对粗体数字)
一旦检测到边缘,我将存储当前位置并以适当的方式将掩码移位一位。因此,经过一个pos。 edge( 01 )我切换到neg。边缘检测( 10 ),反之亦然。在迭代32位有符号数时,我将所有边位置存储在某种向量中。这个向量可以是2维。数组,第一列是单序列的开头,第二列是序列的结尾。此外,我需要对从一个元素到下一个元素的周转进行一些特殊处理。
以下是我的一般问题:您如何看待这种方法?有没有办法更有效地处理这个问题?非常感谢您的帮助。
本
答案 0 :(得分:1)
有效地进行位扫描有各种按位技巧,但如果您使用C ++,则可以利用std::bitset
或boost::dynamic_bitset
迭代位位置。您描述的算法会针对每个块向后迭代,因此您可能希望使用类似32 - (32 - i)
的内容来反转您的位置。
根据体系结构的不同,每个位应该大约需要一个周期。
答案 1 :(得分:0)
有一种有效的(恒定时间)方法可以使用特殊的处理器指令或各种巧妙的技巧来查找单词中的第一个位集(参见例如Position of least significant bit that is set)。
稍微小心一点,你可以向后工作并使用它们扫描第一个,然后做一些掩蔽和位翻转并搜索下一个零,依此类推。
这个可能会给你一个更快的算法,特别是如果序列平均很长,那么快速扫描的增益就会超过比特的成本。