首页 > 其他分享 >C语言整数位运算中的一些技巧

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

时间:2023-05-14 17:37:30浏览次数:44  
标签:return 变量 整数 C语言 异或 uint16 运算

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

标签:return,变量,整数,C语言,异或,uint16,运算
From: https://www.cnblogs.com/sureZ-learning/p/17399693.html

相关文章

  • C语言之环形队列
    一、环形队列的优势环形队列是一种特殊的队列,它可以解决普通队列在使用时空间利用不充分的问题。在环形队列中,当队列满时,队列的尾指针指向队列的起始位置,而不是指向队列的最后一个元素。这样可以在不浪费空间的情况下存储更多的元素。下面我们来详细讲解一下环形队列的......
  • 02-数据类型/常量/变量/运算符
    1.数据类型1.1数据类型分类构造类型--用户自定义的数据类型存储负数使用有符号数字符型也分为有符号数和无符号数#include<stdio.h>intmain(){}1.2基本数据类型bool类型bool不是基本数据类型,使用的时候需要加入头文件#include<stdbool.h>#include<std......
  • c语言的初步认识
    #include<stdio.h>intmain(){printf("hehe\n")return0;}首先看着一组代码,这是c语言最基础的代码,也是在c语言编程学习中最早需要认识的代码。intmain()是一个程序的主函数,也是程序的入口,不能缺少的函数,有且只有能有一个。int是整形的意思,main()前面放一个int指的是main......
  • 01-Linux命令和C语言基础
    1Linux开发环境搭建1.1虚拟机安装1、安装VMWare2、安装ubuntu分区--Linux没有盘符的概念/--5000M/boot--系统启动过程中读取的重要文件/swap--2000M,虚拟内存是物理内存的两倍左右/home--常见的分区Linux文件系统结构是通过文件夹管理的虚拟内存是一段硬......
  • ECMAScript6新特性【对象的扩展(属性的简洁表示法) 对象的新增方法 、运算符的扩展 】(
    ......
  • 数字分频器设计(偶数分频、奇数分频、小数分频、半整数分频、状态机分频|verilog代码|T
    目录一、前言二、偶数分频2.1触发器级联法2.2计数器法2.3verilog代码2.4Testbench2.5仿真结果三、奇数分频3.1占空比非50%奇数分频3.2占空比50%奇数分频3.3Verilog代码3.4Testbench3.5仿真结果四、小数分频4.1双模前置分频法4.2Verilog代码4.3Testbench4.4仿真结果......
  • C语言函数大全-- w 开头的函数(2)
    C语言函数大全本篇介绍C语言函数大全--w开头的函数1.wcstok1.1函数说明函数声明函数功能wchar_t*wcstok(wchar_t*wcs,constwchar_t*delim,wchar_t**ptr);用于将一个长字符串拆分成几个短字符串(标记),并返回第一个标记的地址wchar_t*wcstok(wchar_t*wcs......
  • 哈希表——创建,查找结点——C语言描述
    哈希表——创建,查找结点——C语言描述目录哈希表——创建,查找结点——C语言描述0测试用例框架1定义2数据结构2初始化哈希表与查找(1)代码(2)测试用例(3)打印结果0测试用例框架https://blog.csdn.net/m0_59469991/article/details/127137119?csdn_share_tail=%7B%22type%22%3A%22......
  • C语言程序设计(第四版)谭浩强版 课后答案 第五章
    2、#include<stdio.h>#include<math.h>intmain(){intsign=1,count=0;doublepi=0.0,n=1.0,term=1.0;while(fabs(term)>=pow(10,-6)){pi=pi+term;n=n+2;si......
  • C基础笔记(运算符2)
    运算符(2)  //1.特殊运算符:() .  ->  []//2.算术运算符:+ - * % / ++ --//3.关系运算符:>  >= < <== == !=//4.位操作运算符:& ^ |  << >>//5.逻辑运算符:&&  || !//6.条件运算符:?://7.赋值运算符:= += -=  %= /=......