位运算

位运算

前言

​ 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。

​ 了解位运算之前,让我们首先一下二进制及其原码、反码、补码,方便我们容易的了解位运算。

1. 什么是二进制?

​ 二进制是计算技术中广泛采用的一种数制,二进制数据采用0与1两个数码来表示的数。它的基数是2,进位规则是"逢二进一",借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。

​ 20世纪被称作第三次科技革命的重要标志之一的计算机的发明与应用,因为数字计算机只能识别和处理由‘0’.‘1’符号串组成的代码。其运算模式正是二进制。19世纪爱尔兰逻辑学家乔治布尔对逻辑命题的思考过程转化为对符号"0’’.’‘1’'的某种代数演算,二进制是逢2进位的进位制。0、1是基本算符。因为它只使用0、1两个数字符号,非常简单方便,易于用电子方式实现。

2. 原码、补码、反码

​ 首先,你要知道这些:

二进制的最高位是符号位(“0”代表正数,“1”代表负数);

Java中没有无符号数;

计算机以整数的补码进行运算。

2.1 原码(将一个整数转换成二进制)

​ 以int类型示例,int类型占4个字节,共32位

​ 例如,2 的原码为:00000000 00000000 00000000 00000010

​ -2的原码为:10000000 00000000 00000000 00000010

2.2 反码

​ 正数的反码:与原码相同

​ 负数的反码:原码的符号位不变,其他位取反

​ 例如,-2 的反码为:11111111 11111111 11111111 11111101

2.3 补码

​ 正数的补码:与原码相同

​ 负数的补码:反码+1

​ 例如,-2 的补码为:01111111 11111111 11111111 11111110

位运算符号

含义Pascal语言C语言C#语言Java易语言
按位与a and ba & ba & ba & b位与(a,b)
按位或a or ba | ba | ba | b位或(a,b)
按位异或a xor ba ^ ba ^ ba ^ b位异或(a,b)
按位取反not a~a~a~a位取反(a)
左移a shl ba << ba << ba << b左移(a,b)
带符号右移a shr ba >> ba >> ba >> b/
无符号右移///a >>> b/

运算说明

1. 按位与 &:两位都为1,结果为1

例如,2&3 = 2

2 的原码为: 00000000 00000000 00000000 00000010

3 的原码为: 00000000 00000000 00000000 00000011

2&3 原码为: 00000000 00000000 00000000 00000010 = 2

2. 按位或 |:至少一位为1,结果为1

例如,2|3 = 3

2 的原码为: 00000000 00000000 00000000 00000010

3 的原码为: 00000000 00000000 00000000 00000011

2|3 原码为: 00000000 00000000 00000000 00000011 = 3

3. 按位异或 ^:两位一个为1、一个为0,结果为1

例如,2|3 = 3

2 的原码为: 00000000 00000000 00000000 00000010

3 的原码为: 00000000 00000000 00000000 00000011

2^3 原码为: 00000000 00000000 00000000 00000001 = 1

4. 按位取反 ~:0变成1、1变成0

例如,~2 = -3

对2的原码取反:11111111 11111111 11111111 11111101 (取反后结果的补码,也就是-3的补码。我们需要从补码推出原码,才能得到-3)

​ 转换成反码: 11111111 11111111 11111111 11111100 (补码减1)

转换成原码: 10000000 00000000 00000000 00000011 =-3 (符号为不变,其他位取反)

简单应用

1. 位运算交换
a=a^b;
b=a^b;       
a=a^b;
2. 消除x的最后一位的1
x & (x-1)
x = 1100
x-1 = 1011
x & (x-1) = 1000
  1. 数组中,只有一个数出现一次,剩下都出现三次,找出出现一次的。
//Given [1,2,2,1,3,4,3], return 4
//因为只有一个数恰好出现一个,剩下的都出现过两次,所以只要将所有的数异或起来,就可以得到唯一的那个数。
int a[7]={1,2,2,1,3,4,3};
    int ans=0;
    for(int i=0;i<7;i++){
        ans^=a[i];
    }
    System.out.printf(ans);

总结

  1. 正数的原码、反码、补码都一样;

  2. 负数的反码 = 原码的符号位不变,其他位取反;

  3. 负数的补码 = 反码+1;

  4. 0的原码、反码、补码都是0;

  5. 计算机以补码进行运算;

  6. 取反不同于反码;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值