C语言整数位运算中的一些技巧

1 与(&)

1. 与(&)运算实现求余%运算

在计算机里整数求余运算比较低效,在对2的整数幂进行求余时,可以使用&来优化

如: a对2 ^ n (n为自然数)求余:

a % (2 ^ n)  = a & ((2 ^ n) - 1)  // 如 a % 4 = a & 0x3

判断奇数偶数时,可以与1相与

if (n & 0x1 == 0x1) {
    // printf("n 是奇数");
}

2. 计算一个整数2进制中有多少个1

利用n = n & (n - 1) 用来将最低位的1变为0

count = 0
while (n)
{
   n &= (n - 1);
   count++;
}

3. 判断一个数是否是2的整数次幂

如:判断n是否是2的整数次幂,2的整数次幂即整数的二进制表示中只有一个1,如(2--> 010b 4-->0100b等)

if (! (n & (n - 1))) {
    // printf("n is 2 的整数次幂");
}

4. 获取一个整数2进制最低位的1(最右边的1)

n & -n        // 最低位的1被与运算保留下来, 同样可以使用 n & -n == n 来判断n是不是2的整数次幂
n & (~n + 1)  // ~n+1即对n取反再加1,这个即得到-n的补码 ~n+1=-n

有时候,我们希望得到整数二进制最低位1的位置:

/* Find the First bit in uint8_t data */
uint8_t FindFirstBit_u8(uint8_t n)
{
    n = (n-1) & ~n;
    n = ((n & 0xAA) >> 1) + (n & 0x55);
    n = ((n & 0xCC) >> 2) + (n & 0x33);
    n = ((n & 0xF0) >> 4) + (n & 0x0F);
    return n;
}
/* Find the First bit in uint16_t data */
uint16_t FindFirstBit_u16(uint16_t n)
{
    n = (n-1) & ~n;
    n = ((n & 0xAAAA) >> 1) + (n & 0x5555);
    n = ((n & 0xCCCC) >> 2) + (n & 0x3333);
    n = ((n & 0xF0F0) >> 4) + (n & 0x0F0F);
    n = ((n & 0xFF00) >> 8) + (n & 0x00FF);
    return n;
}

/* Find the First bit in uint32_t data */
uint32_t FindFirstBit_u32(uint32_t n)
{
    n = (n-1) & ~n;
    n = ((n & 0xAAAAAAAA) >> 1) + (n & 0x55555555);
    n = ((n & 0xCCCCCCCC) >> 2) + (n & 0x33333333);
    n = ((n & 0xF0F0F0F0) >> 4) + (n & 0x0F0F0F0F);
    n = ((n & 0xFF00FF00) >> 8) + (n & 0x00FF00FF);
    n = ((n & 0xFFFF0000) >> 16) + (n & 0x0000FFFF);
    return n;
}

2 或(|)

(待补充)

3 异或(^)

1. 异或的重要性质

  • 一个数与自身异或,总是为0

    x ^ x = 0
    

    可以用来判断两个变量是否相等,如c语言中判断,变量a与b是否相等

    if ((a ^ b) == 0)
    {
       // printf("a 与 b相等") 
    }
    
  • 一个数与0异或,总是为自身

    x ^ 0 = x
    

2. 不使用临时变量交换两个整数的值

交换两个整数的值,通常做法是借助临时变量,然后交换,如:

tmp = a
a = b
b = tmp

利用异或的性质,不用临时变量也能交换两个数的值,过程如下:

a ^= b
b ^= a
a ^= b

4 移位

  • 左移n位等于原数值以2的n次方,要注意避免溢出(正数变负数)

  • 逻辑右移n位等于原数值以2的n次方,注意负数右移的情况:

    x >> n = floor(x / (2 ^ n))
    // 例如: -5 >> 1 = -3 而非-2
    

参考:

  1. 位运算的妙用
  2. 计算二进制数中1的个数
posted @ 2023-05-14 17:18  sureZ_ok  阅读(203)  评论(0编辑  收藏  举报