找出在C中没有循环的x除以2的频率

时间:2011-02-17 22:14:14

标签: c integer bit-manipulation

我正在寻找一种方法来查找在不使用循环,递归或对数的情况下将常数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);

5 个答案:

答案 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));

iv中最低设置位的索引。该公式适用于v的值,最多可达200​​0个零位,远大于任何整数类型。

请参阅此处获取解释:

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留给读者练习。