C 如何有效地查找一系列数字的按位或
给定一个数字[a,b]的范围,如何有效地查找该范围内所有数字的按位或。对范围[a,b]运行循环并单独计算所有数字的位或,对于非常大的范围来说太耗时了,因此这不是选项。任何形式2n-1的数字都将是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的最大幂,所以我们将永远无法在数字中获得更多的位 所以基本上只有两个病例。如果范围
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;
}