如何有效地找到一系列数字的按位OR

时间:2017-04-13 06:31:24

标签: c algorithm bit-manipulation bitwise-operators bitwise-or

给定数字范围[a,b],如何有效地找到此范围内所有数字的按位OR。为范围[a,b]运行循环并单独计算所有数字的按位OR对于非常大的范围来说太耗时,所以这不是选项。

3 个答案:

答案 0 :(得分:4)

任何数量的形式2 n -1将是n 1的位模式。当你对它下面的任何数字进行OR运算时,得到2 n -1。因此,可以忽略范围内最高2 n -1以下的所有数字。

范围中的下一个数字将是1,后跟n 0 s,当您与此进行OR时,您将获得n+1 {{1} }秒。由于我们选择上述数字作为2的最大功率,我们将永远不会再获得该数字的位数。

所以基本上只有2个案例。如果范围的顶部是2 n -1,则结果是具有1 n位的数字。否则它是1 1位。

以上假设范围包括2 n -1值。如果没有,只需尝试循环(可能会进行一些优化,但我无法想到它们。)

答案 1 :(得分:2)

而不是为所有数字执行此操作,您可以为所有位置执行此操作。这将只需要log(n)步骤。

所以让我们试着想象 - 单位何时会是1?如果上限或下限是奇数或者它们之间有一个数字。所以要么降低%2 == 1或更低!=更高。

很棒,我们有单位。现在如果从上部和下部位移除较低的一位并重复,我们得到其他位置。

只有特殊情况,如果更低==更高。在那种情况下,我们返回下层。

以下是代码 -

unsigned int bitwiseor(unsigned int a, unsigned int b){
    if (a==b)
        return a;
    unsigned final = 0;
    unsigned rev = 0;
    while(b){
        final*=2;
        if (a%2==1 || a != b)
            final++;
        a/=2;
        b/=2;
    }
    while(final){
        rev *= 2;
        rev += final % 2;
        final/=2;
    }
    return rev;
}

第二个循环是保留位序列。

在这里演示 - https://ideone.com/MCIugW

感谢@Meixner提供的驱动程序代码。

答案 2 :(得分:0)

#include <stdio.h>
#include <stdlib.h>

int dumb(int a, int b)
{
   int z=0;

   while(a<=b) z|=a++;
   return z;
}

int smart(int a, int b)
{
   int d,z;
   if(a>b) return 0;
   d=b-a+1;
   z=0;
   while(d>1) { z=(z<<1)|1; d>>=1; }
   d=z;
   z|=a;
   a+=d;
   while(a<=b) z|=a++;
   return z;
}


int main(int argc, char *argv[])
{
   int a,b;
   for(a=0;a<1000;a++) {
      for(b=a;b<1000;b++) {
         int z1=dumb(a,b);
         int z2=smart(a,b);
         if(z1!=z2) {
            printf("fail %d %d\n",a,b);
         }
      }
   }
   return 0;
}