我正在寻找一种方法来查找在不使用循环,递归或对数的情况下将常数x除以2(而不是得到余数)的频率。由于这与查找最低有效非零位的索引的问题相同,我希望有一些方法可以使用按位运算来执行此操作。不幸的是我无法想出来。有什么想法吗?
背景:我有一个循环,在每次迭代时将计数器加倍,直到它不再除以常数x。我希望这个循环能够展开,但NVIDIA CUDA编译器不够聪明,无法计算出迭代次数,所以我想重写循环,使得迭代次数对编译器来说变得更加明显: / p>
for(i=1; CONST & i == 0; i *= 2)
bla(i);
应该变得像
#define ITERATIONS missing_expr_with_CONST
for(i=0; i < ITERATIONS; i++)
fasel(i);
答案 0 :(得分:7)
这可以使用this code for 32 bit numbers直接解决(我没有信用)。
unsigned int v; // find the number of trailing zeros in 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];
答案 1 :(得分:3)
您也可以使用纯算术而不使用查找表(De Bruijn序列方法需要查找表),但它很昂贵。在这里:
m = (v&-v)-1;
i = ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12));
i
是v
中最低设置位的索引。该公式适用于v
的值,最多可达2000个零位,远大于任何整数类型。
请参阅此处获取解释:
Is there any way to compute the width of an integer type at compile-time?
答案 2 :(得分:0)
执行右移,然后左移并检查与AND的相等性,每次检查成功时增加一个计数器。
int powerOfTwo(int x) {
int counter = 0;
while(x > 0) {
int y = x >> 1;
y <<= 1;
if(x ^ y) {
counter++;
} else {
break;
}
x >>= 1;
}
return counter;
}
这使用循环...我可以想到消除循环的方法,但它基本上是“展开”循环。
答案 3 :(得分:0)
这可以通过循环轻松完成(这可能不是100%正确,因此可以随意更正):
int leastSigBit(int num) {
int result;
for(result = 0; num & 1 != 1; ++result)
num >>= 1;
return result;
}
但是我相信没有循环就不可能这样做,因为你在未知位置搜索一下,因此必须检查所有可能的位置。
编辑根据更新的说明修改。
答案 4 :(得分:0)
如果“ pow”不算为对数,则可以通过以下方法对所有数字进行计算 不只是“ 2”。乘而不是除的反函数是 还包括完整性。
GLSL代码:
//://////////////////////////////////////////////////////////://
//://///://
//:IFDO: Move this somewhere more general IF you //://///://
//: ever find a need to call it from somewhere //://///://
//: else. //://///://
int //://///://
ES2_AA2_Di2( //://///://
int B //:BASE:(Affected_Number) //://///://
, int N //:NUMB:(Number_Of_Times_To_Divide_By_Two) //://///://
){ //://///://
//:programtic_equivalent_of_formula_below:---------------://
//: ://
//: var b = B; ://
//: for( var n = 0; n < N; n++ ){ ://
//: b = b / 2; ://
//: };; ://
//: return( b /** R **/ ); ://
//:______________________________________________________://
int R = int( float( 0 )
+ float( B )
/ pow( float(2) , float(N) )
);;
return( R );
return( int(0) );
}//://////////////////////////////////////////| ES2_AA2_Di2 |://
//://////////////////////////////////////////////////////////://
JavaScript代码:
//:B: Base //: MUL:A_NUMBER_OF_TIMES ://
//:N: N number of times. //: MUL:A_NUMBER_OF_TIMES ://
const AA2_Mu2=( B, N )=>{ return( B * (pow(2,N) ) ); };
const AA2_Mu3=( B, N )=>{ return( B * (pow(3,N) ) ); };
const AA2_Mu4=( B, N )=>{ return( B * (pow(4,N) ) ); };
const AA2_Mu5=( B, N )=>{ return( B * (pow(5,N) ) ); };
//:B: Base //: DIV:A_NUMBER_OF_TIMES ://
//:N: N number of times. //: DIV:A_NUMBER_OF_TIMES ://
const AA2_Di2=( B, N )=>{ return( B / (pow(2,N) ) ); };
const AA2_Di3=( B, N )=>{ return( B / (pow(3,N) ) ); };
const AA2_Di4=( B, N )=>{ return( B / (pow(4,N) ) ); };
const AA2_Di5=( B, N )=>{ return( B / (pow(5,N) ) ); };
抄写C留给读者练习。