• 位运算和典型应用详解



    位运算的符号
      与运算:&

      或运算:|

      异或运算:^

      非运算:~

      移位运算:>>和<<


    一. 逻辑运算符
    1. & 位与运算

    1) 运算规则
    位与运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑与运算。例如:int型常量4和7进行位与运算的运算过程如下:
    4=0000 0000 0000 0100 &7 =0000 0000 0000 0111= 0000 0000 0000 0100
    对于负数,按其补码进行运算。例如:例如:int型常量-4和7进行位与运算的运算过程如下: -4=1111 1111 1111 1100 &7 =0000 0000 0000 0111= 0000 0000 0000 0100
    2) 典型应用
    (1) 清零
    清零:快速对某一段数据单元的数据清零,即将其全部的二进制位为0。例如整型数a=321对其全部数据清零的操作为a=a&0x0。 321=0000 0001 0100 0001 &0=0000 0000 0000 0000
    = 0000 0000 0000 0000
    (2) 获取一个数据的指定位
    获取一个数据的指定位。例如获得整型数a=的低八位数据的操作为a=a&0xFF。321=
    0000 0001 0100 0001 & 0xFF =0000 0000 1111 11111
    = 0000 0000 0100 0001
    获得整型数a=的高八位数据的操作为a=a&0xFF00。==a&0XFF00==
    321=0000 0001 0100 0001 & 0XFF00=1111 1111 0000 0000
    = 0000 0001 0000 0000
    (3)保留数据区的特定位
    保留数据区的特定位。例如获得整型数a=的第7-8位(从0开始)位的数据操作为: 110000000
    321=0000 0001 0100 0001 & 384=0000 0001 1000 0000
    =0000 0001 0000 0000
    (4)判断一个数X是否是2的N次方,不可以使用循环语句
    如果X减去1后(低一位并且二进制的每一位都是1),这个数与X做与运算,答案若是0,则X是2的N次方。
    !(X&(X-1))

    2. | 位或运算
    1) 运算规则
    位或运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑或运算。例如:int型常量5和7进行位或运算的表达式为5|7,结果如下:5= 0000 0000 0000 0101
    | 7= 0000 0000 0000 0111=0000 0000 0000 0111
    2) 主要用途
    (1) 设定一个数据的指定位。例如整型数a=321,将其低八位数据置为1的操作为a=a|0XFF。321= 0000 0001 0100 0001 | 0000 0000 1111 1111=0000 0000 1111 1111
    逻辑运算符||与位或运算符|的区别
    条件“或”运算符 (||) 执行 bool 操作数的逻辑“或”运算,但仅在必要时才计算第二个操作数。 x || y , x | y 不同的是,如果 x 为 true,则不计算 y(因为不论 y 为何值,“或”操作的结果都为 true)。这被称作为“短路”计算。
    3. ^ 位异或
    1) 运算规则
    位异或运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑异或运算。只有当对应位的二进制数互斥的时候,对应位的结果才为真。例如:int型常量5和7进行位异或运算的表达式为5^7,结果如下:5=0000 0000 0000 0101^7=0000 0000 0000 0111
    = 0000 0000 0000 0010
    2) 典型应用
    (1)定位翻转
    定位翻转:设定一个数据的指定位,将1换为0,0换为1。例如整型数a=321,,将其低八位数据进行翻位的操作为a=a^0XFF;
    (2)数值交换
    数值交换。例如a=3,b=4。在例11-1中,无须引入第三个变量,利用位运算即可实现数据交换。以下的操作可以实现a,b两个数据的交换:
    a=a^b;
    b=b^a;
    a=a^b;
    4.~ 位非
    位非运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行逻辑非运算。

    二.位移运算符
    1.位左移
    左移运算的实质是将对应的数据的二进制值逐位左移若干位,并在空出的位置上填0,最高位溢出并舍弃。例如int a,b;
    a=5;
    b=a<<2;
    则b=20,分析过程如下:
    (a)10=(5)10=(0000 0000 0000 0101)2
    b=a<<2;
    b=(0000 0000 0001 0100)2=(20)10
    从上例可以看出位运算可以实现二倍乘运算。由于位移操作的运算速度比乘法的运算速度高很多。因此在处理数据的乘法运算的时,采用位移运算可以获得较快的速度。
    提示 将所有对2的乘法运算转换为位移运算,可提高程序的运行效率
    2.位右移
    位右移运算的实质是将对应的数据的二进制值逐位右移若干位,并舍弃出界的数字。如果当前的数为无符号数,高位补零。例如:
    int (a)10=(5)10=(0000 0000 0000 0101)2
    b=a>>2;
    b=(0000 0000 0000 0001)2=(1)10
    如果当前的数据为有符号数,在进行右移的时候,根据符号位决定左边补0还是补1。如果符号位为0,则左边补0;但是如果符号位为1,则根据不同的计算机系统,可能有不同的处理方式。可以看出位右移运算,可以实现对除数为2的整除运算。
    提示 将所有对2的整除运算转换为位移运算,可提高程序的运行效率
    3.复合的位运算符
    在C语言中还提供复合的位运算符,如下:
    &=、!=、>>=、<<=和^=
    例如:a&=0x11等价于 a= a&0x11,其他运算符以此类推。
    不同类型的整数数据在进行混合类型的位运算时,按右端对齐原则进行处理,按数据长度大的数据进行处理,将数据长度小的数据左端补0或1。例如char a与int b进行位运算的时候,按int 进行处理,char a转化为整型数据,并在左端补0。
    补位原则如下:
    1) 对于有符号数据:如果a为正整数,则左端补0,如果a 为负数,则左端补1。
    2) 对于无符号数据:在左端补0。
    4.例子
    例11-2 获得一个无符号数据从第p位开始的n位二进制数据。假设数据右端对齐,第0位二进制数在数据的最右端,获得的结果要求右对齐。
    #include <stdio.h>
    /*getbits:获得从第p位开始的n位二进制数 */
    unsigned int getbits(unsigned int x, unsigned int p, unsigned n)
    {
    unsigned int a;
    unsigned int b;
    a=x>>(p+1);
    b=~(~0<<n);
    return a&b;
    }
    提示 在某一平台进行程序开发时,首先要求了解此系统的基本数据类型的有效范围, 对涉及的位运算进行评估,特别是要对边界数据进行检测,确保计算正确。

    原文标题:位运算及其应用详解

    原文地址:http://blog.chinaunix.net/uid-21411227-id-1826986.html

  • 相关阅读:
    HttpClient调用RestFul接口(post和get方式)
    mysql权限异常
    javascript:用法
    Java哈希值HashCode理解
    Java的CountDownLatch和CyclicBarrier的理解和区别
    Java并发编程与技术内幕:ThreadGroup线程组应用
    面试官: 谈谈什么是守护线程以及作用 ?
    java 成员变量 静态成员变量 方法 静态方法初始化顺序
    【java并发核心一】Semaphore 的使用思路
    threadlocal原理及常用应用场景
  • 原文地址:https://www.cnblogs.com/zqifa/p/7120315.html
Copyright © 2020-2023  润新知