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

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。C语言整数位运算中的一些技巧,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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的个数

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/201891.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!