使用按位逻辑运算实现位向量

时间:2016-04-24 02:36:11

标签: bit-manipulation

Pearls对编程问题2提出了这个问题。我无法理解其解决方案。

这是书中写的解决方案。

cat somefile | tr -d '\n'

我已经在我的编译器中运行了这个,我已经查看了另一个讨论这个问题的问题,但我仍然不明白这个解决方案的工作原理。

为什么要进行[i>> SHIFT]?为什么它只是一个[i] = 1;为什么我需要向右移动5次?

2 个答案:

答案 0 :(得分:3)

32是2 5 ,所以5位右移相当于除以32.所以通过a[i>>5],你将i除以32弄清楚数组的哪个元素包含位i - 每个元素有32位。

同时& MASK相当于mod 32,因此1<<(i & MASK)为单词中的特定位构建1位掩码。

答案 1 :(得分:1)

将int i的32位(从位0开始到位31)分成两部分。

  • 第一部分是最重要的位31到5.使用此部分查找用于实现位数组的int数组(此处称为[])中的索引。最初,整个整数数组都被清零。

由于[]中的每个int都是32位,因此它可以跟踪那些32位的32个int。我们将每个输入i除以32以在[]中找到应该跟踪这个i的int。

每次将数字除以2时,它实际上是右移一次。要将数字除以32,您只需将其右移5次即可。这正是我们通过过滤掉第一部分得到的。

  • 第二部分是最低有效位0到4.将数字分类到正确的索引后,使用此部分设置存储在此索引的[]中的零的特定位。显然,如果已经设置了该索引处的零点,则该索引处的值将不再为零。

如何获得第一部分?右移i乘以5(即i&gt;&gt; SHIFT)。

如何获得第二部分?按11111对i进行按位AND。(11111) 2 = 0x1F,定义为MASK。所以,我和我MASK将给出由i的最后5位表示的整数值。

最后5位告诉你在[]中的数字内有多少位。例如,如果i为5,则要设置[]的索引0中的位,并且您特别希望将int值的5 th 位设置为[0]。

指数设置= 5/32 =(0101>> 5)= 0000 = 0.

在[0]

中设置= 5 th 位的位
  • = a [0]&amp; (1 <&lt; 5)
  • = a [0]&amp; (1&lt;(00101&amp; 11111))。

设置给定i的位

  1. 通过[i&gt;&gt;设置获取int 5]
  2. 通过将1总共i%32次向左推,即1&lt;&lt;&lt; (i&amp; 0x1F)
  3. 只需将该位设置为[i>&gt; 5] = a [i>&gt; 5] | (1&lt;(i&amp; 0x1F));
  4. 可以缩短为[i>&gt; 5] | =(1&lt;(i&amp; 0x1F));
  5. 获取/测试给定i的位

    1. 通过[i&gt;&gt;获取所需位所在的int 5]
    2. 生成一个数字,其中所有位除了i&amp; 0x1F位为0.您可以通过否定1&lt;&lt; (i&amp; 0x1F)。
    3. 和上面生成的数字一起使用[]中存储在此索引处的值。如果该值为0,则该特定位为0.如果该值不为零,则该位为1.
    4. 在代码中,您只需返回[i&gt;&gt; 5]&amp; (1&lt;(i&amp; 0x1F))!= 0;
    5. 清除给定i的位:表示将i的位设置为0。

      1. 通过[i&gt;&gt;获取位所在的位置5]
      2. 得到1&lt;&lt;&lt; (i&amp; 0x1F)
      3. 反转1&lt;&lt;&lt; (i&amp; 0x1F)使i的位为0。
      4. 和此索引处的数字以及步骤3中生成的数字。这将清除我的位,使所有其他位保持不变。
      5. 在代码中,这将是:a [i&gt;&gt; 5]&amp; =〜(1&lt;(i&amp; 0x1F));