C 如何有效地查找一系列数字的按位或

C 如何有效地查找一系列数字的按位或,c,algorithm,bit-manipulation,bitwise-operators,bitwise-or,C,Algorithm,Bit Manipulation,Bitwise Operators,Bitwise Or,给定一个数字[a,b]的范围,如何有效地查找该范围内所有数字的按位或。对范围[a,b]运行循环并单独计算所有数字的位或,对于非常大的范围来说太耗时了,因此这不是选项。任何形式2n-1的数字都将是n1的位模式。当你或这个下面有任何数字时,你得到2n-1。因此,该范围内最高2n-1以下的所有数字都可以忽略 该范围内的下一个数字将是一个1,后跟n0s,当您或使用该数字时,您将得到n+11s。因为我们选择了上面的数字作为2的最大幂,所以我们将永远无法在数字中获得更多的位 所以基本上只有两个病例。如果范围

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

任何形式2n-1的数字都将是
n
1的位模式。当你或这个下面有任何数字时,你得到2n-1。因此,该范围内最高2n-1以下的所有数字都可以忽略

该范围内的下一个数字将是一个
1
,后跟
n
0
s,当您或使用该数字时,您将得到
n+1
1
s。因为我们选择了上面的数字作为2的最大幂,所以我们将永远无法在数字中获得更多的位

所以基本上只有两个病例。如果范围的顶部为2n-1,则结果是一个带有
n
1
位的数字。否则它是
n+1
1位

上述假设范围包括2n-1值。如果没有,就试试这个循环(可能有一些优化可以实现,但我想不出来) #包括 int dumb(int a,int b) { int z=0; 而(ab)返回0; d=b-a+1; z=0; 而(d>1){z=(z=1;} d=z; z |=a; a+=d;
而(a不是对所有数字都这样做,而是对所有位置都这样做。这只需要记录(n)个步骤

让我们试着想象一下,什么时候单位的位置是1?如果上面或下面是奇数,或者它们之间有一个数字,那么下面的%2==1或下面的!=upper

很好,我们得到了单位的位置。现在,如果从上下两个位置移除下一个位置,然后重复,我们得到其他位置

如果lower==upper,则只有一种特殊情况。在这种情况下,我们返回lower本身

以下为守则-

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;
}
第二个循环只是保留位序列

这里演示-


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

太糟糕了。C没有比循环更好的功能了。如果目标arch有合适的命令,你可以尝试内联汇编。写下一些连续数字的位模式。写下按位或结果。对许多不同的范围执行此操作。你能找到一个模式吗?如果范围包括排除任何2^n-1值,这将是全部1,当你或它与任何你将得到全部1,因此你可以跳过它下面的所有数字。因此,找到你的范围内最高的2^n-1值,并从那里开始循环。这是正确的,直到最后一段,其中不考虑范围的底部。(例如,[9,10]的结果)是1001 | 1010=1011,而你的方法会说它是1111)@Barmar不完整的,当没有2^n-1在这个范围内。@AjayBrahmakshatriya是的,当我昨晚要睡觉的时候,我意识到了这一点。
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;
}