位运算技巧

位运算技巧

  • 使用位运算交换两个数值
void swap(int* a, int* b)
{
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}
  • 奇偶校验码
// 有奇数个1返回1,有偶数个1返回0。
int check_bit(int n)
{
    n ^= n >> 1;
    n ^= n >> 2;
    n ^= n >> 4;
    n ^= n >> 8;
    n ^= n >> 16;
    return n & 1;
}
  • 二进制中 1 的个数
uint32_t method_1_uint32_popcount(uint32_t n)
{
    n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
    n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
    n = (n & 0x0f0f0f0f) + ((n >> 4) & 0x0f0f0f0f);
    n = (n & 0x00ff00ff) + ((n >> 8) & 0x00ff00ff);
    n = (n & 0x0000ffff) + ((n >> 16) & 0x0000ffff);
    return n;
}

uint32_t method_2_uint32_popcount(uint32_t n)
{
    n = n - ((n >> 1) & 0x55555555);
    n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
    n = (n + (n >> 4)) & 0x0f0f0f0f;
    n = n + (n >> 8);
    n = n + (n >> 16);
    return n & 0x3f;
}

uint32_t method_3_uint32_popcount(uint32_t n)
{
    n = n - ((n>>1) & 0x55555555);
    n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
    return ((n + (n >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
  • 求 1/sqrt(n)
float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

#ifndef Q3_VM
#ifdef __linux__
    assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
 return y;
}
  • 其他
n & ( n + 1 ) // 把右边连续的1变成0
n & ( n - 1 ) // 把右边第一个1变成0
n | ( n + 1 ) // 把右起第一个0变成1
n | ( n - 1 ) // 把右起连续的0变成1
n ^ ( n + 1 ) // 取右边连续的1
n & -n 或 n & ( n ^ ( n - 1 ) )   // 去掉右起第一个1的左边
( n << x ) | ( x >> ( 32 - x ) )  // 高低位交换,前x位
( n ^ (n >> 31) ) - (n >> 31)     // 有符号整数计算绝对值

posted on 2022-09-11 15:45  LambdaQ  阅读(43)  评论(0)    收藏  举报