大家在阅读一些算法或者一些开源框架的时候,总会见到~,>>,>>>,|这种大量的位运算,因此想要读明白

这部分代码,对于计算机的二进制操作以及位运算是必须要了解的,那么本篇我们就开始详细的学习二进制

操作以及位运算

整数的二进制运算

要理解整数的二进制,我们先来看看最熟悉的十进制,例如123这个值,如果按照十进制,是如何计算出来的呢?其实123表示1x(10^2) + 2 x (10^1) + 3 x (10^0),表示的是各个位置上的数值含义之和,每个位置的数值含义和所处的位数有关系,从右开始往左,从个位开始,到高位,个位的数值则是(数值 x (10^0)),每多一位数,则是10的次方多一位,也就是说,每一个位置都有一个位权,从右到左,第一位是1,第二位是10,第三位是100,以此类推。

而二进制有何不同呢?首先十进制每一位可以存在十个数值,分别为0-9,而在二进制中,每一位只能存在0和1两个值,同样的二进制也存在位权的概念,从右到左,第一位为1,然后每多一位依次乘以2,第二位为2,第三位为4,以此类推,比如我们常见的十进制数值2,在二进制中则为10表示,而数值3则是11表示,数值7则是111,数值10则是1010。

ps:计算规则则是拿十进制的数值不停的除以2,如果能整除就是余数为0,则当前位为0,不能整除则是余数为1,当前位为1,依次除到小于2为止,这个时候我们将当前值反过来,则是对应的二进制值,例如:

十进制转换二进制.png

42从上到下的结果为010101,而计算完毕以后,则是从下往上读取,则为101010,即二进制的结果为101010

负数的二进制

前面我们说了正整数的二进制运算规则,为什么不是整个整数范围的二进制运算呢?原来这个和计算机表示有关系,计算机无法读取负数,只能对应做加法,所以当一个负数转为二进制的时候,便有了新的表示法,我们称之为补码表示法

补码/反码/原码

首先我们要明白一点,二进制的首位用来表示正数还是负数,如果是0则是正数,1为负数,剩下的才是对应的值,但是需要注意的一点是,计算机的计算中负数也会转换为正数来计算,而转换的过程,则是先获取绝对值(正数)得二进制结果,此过程称之为原码,然后给当前的补码每一位反过来,则是最终负数的结果,此过程称之为反码,接着通过给当前反码+1的结果,称之为补码,****。当然由于数值类型不同,字节数不同,我们知道每一个字节占8个比特位,整数有四种类型,分别为byte、short、int、long,分别占1、2、4、8字节,即8、16、32、64个比特位,所以当位数不够的时候,高位会补0(从左到右则是高位到低位)。

例如当前值为-1,首先我们获取绝对值1,首先是一个字节的值,也就是8个比特位,1的二进制原码为1,前面补0,则是00000001,接着我们将当前值反过来,得到反码11111110,然后对反码+1则是补码11111111,所以-1得值就是11111111。

例如-127,绝对值为127,原码为01111111,反码为10000000,补码则是10000001,其他的负数都是如此。

位运算

前面介绍了整数的二进制操作,那么在计算机操作中,往往对二进制辅以位运算,以此来达到快速运算的结果,接下来,就开始学习计算机中的位运算操作,首先将所有的位运算列出来,如下:

运算符

说明

<<

左移位,在低位处补0

>>

右移位,若为正数则高位补0,若为负数则高位补1

>>>

无符号右移位,无论正负都在高位补0

&

与(AND),对两个整型操作数中对应位执行布尔代数,两个位都为1时输出1,否则0。

|

或(OR),对两个整型操作数中对应位执行布尔代数,两个位都为0时输出0,否则1。

~

非(NOT),一元运算符。

^

异或(XOR),对两个整型操作数中对应位执行布尔代数,两个位相等0,不等1。

<<=

左移位赋值。

>>=

右移位赋值。

>>>=

无符号右移位赋值。

&=

按位与赋值。

|=

按位或赋值。

^=

按位异或赋值。

如此多的运算,到底是如何计算的呢?

(<

假设当前有值int a = 5,操作为5 << 3,则是对5做左移三位的操作,那么具体操作步骤是什么呢?

1.将5转为32比特位(int)的二进制,得出结果0000 0000 0000 0000 0000 0000 0000 0101

2.这个时候将整体朝左移动三位,超过三十二位的高位舍弃(少舍弃一位,留下一位作为正负数的符号位,即正数最高位补0,负数最高位补1),低位不足补0,则是0000 0000 0000 0000 0000 0000 0010 1000 ,将当前二进制转换为十进制,则是40,所以最终计算的结果为40

public class LeftMoving{

public static void main(String[] args){

int a = 5;

System.out.println("5<<3="+(a << 3));//5<<3=40

}

}

(>>)右移位

假设当前值int a = 5,操作为5>>1,则是对5右移1位的操作,具体步骤如下:

1.将5转为32比特位的二进制,结果为0000 0000 0000 0000 0000 0000 0000 0101

2.将整体二进制的结果右移1位,如果本身为正数,首个最高位补0,负数首个最高位补1,其他高位补0,超过的低位舍弃,结果为00000 0000 0000 0000 0000 0000 0000 010,将这个值转为十进制为2,所以最终结果为2

public class NegativeRightMoving{

public static void main(String[] args){

int a = 5;

System.out.println("5>>1="+(a>>1));//5>>1=2

}

}

(>>>)无符号右移

这里我们假设值int a = -5,操作为-5>>>1,操作如下:

1.原码为0000 0000 0000 0000 0000 0000 0000 0101

2.反码为1111 1111 1111 1111 1111 1111 1111 1010

3.补码为1111 1111 1111 1111 1111 1111 1111 1011

4.整体右移1位,高位补0,低位超过部分舍弃,则为0111 1111 1111 1111 1111 1111 1111 1101,转为十进制为2147483645 ,所以最终结果为2147483645

public class UnsignedRightMoving{

public static void main(String[] args){

int a = -5;

System.out.println("-5>>>1="+(a>>>1));//-5>>>1=2147483645

}

}

ps:一定要分清楚无符号右移和右移操作的区别,右移位运算符>>,若操作的值为正,则在高位插入0;若值为负,则在高位插入1,右移补零操作符>>>,无论正负,都在高位插入0

(&)位与运算符

假设值int a = 129,操作为129&128,具体步骤如下:

1.129转为二进制0000 0000 0000 0000 0000 0000 1000 0001,128转二进制为0000 0000 0000 0000 0000 0000 1000 0000

2.从最高位开始比较,同一位的两个值都为1则是1,否则为0,则最终结果为0000 0000 0000 0000 0000 0000 1000 0000 ,即128

public static void main(String[] args){

System.out.println("129&128="+(129&128));//129&128=128

}

(|)位或运算符

假设值int a = 129,操作为129|128,具体步骤如下:

1.129转为二进制0000 0000 0000 0000 0000 0000 1000 0001,128转二进制为0000 0000 0000 0000 0000 0000 1000 0000

2.从最高位开始比较,同一位的两个值有一个为1则是1,否则为0,则最终结果为0000 0000 0000 0000 0000 0000 1000 0001即129

public static void main(String[] args){

System.out.println("129|128="+(129|128));//129|128=129

}

(~)位非运算符

假设值为37,操作为~37,具体步骤如下:

1.37转为二进制为00000000 00000000 00000000 00100101

2.~操作是指如果每一位的值为0,则是1,如果为1,则是0,所以整体取反,结果为11111111 11111111 11111111 11011010

3.由于当前获取的结果首位为1,代表值为负数,那么我们通过当前补码计算原码,首先将补码-1得到反码,则为11111111 11111111 11111111 11011001,然后整体取反,则为00000000 00000000 00000000 00100110 ,转为10进制为38,由于是负数,则最终结果为-38

public static void main(String[] args){

System.out.println("~37="+(~37));//~37=-38

}

(^)位异或运算

假设当前值为8,操作为8^11,具体操作如下:

1.8转为二进制0000 0000 0000 0000 0000 0000 0000 1000 ,11转为二进制为0000 0000 0000 0000 0000 0000 0000 1011

2.^运算符则是比较每一位的值是否一致,一致为0,否则为1,所以比较的结果为0000 0000 0000 0000 0000 0000 0000 0011 ,转为十进制结果为3

public static void main(String[] args){

System.out.println("8^11="+(8^11));//8^11=3

}

(<<=)左移赋值

假设当前有值int a = 5,操作为a <<= 3,那么具体操作步骤是什么呢?

1.先将5做左移三位的操作,得出结果为40(此步骤与<

2.然后将最终结果重新赋值给a,即a为40

public class LeftMoving{

public static void main(String[] args){

int a = 5;

a <<= 3;//a = a << 3

System.out.println(a);//40

}

}

(>>=)右移赋值

假设当前值int a = 5,操作为a >>= 1,则是对5右移1位的操作,具体步骤如下:

1.首先将a按照5 >> 1的操作,得到结果为2

2.将得到的结果2赋值给a,即a=2

public class NegativeRightMoving{

public static void main(String[] args){

int a = 5;

a >>= 1; //a = a >> 1;

System.out.println(a);//2

}

}

(>>>=)无符号右移赋值

这里我们假设值int a = -5,操作为a >>>= 1,操作如下:

1.5 >>> 1的结果为2147483645

2.将结果2147483645 赋值给a,则a=2147483645

public class UnsignedRightMoving{

public static void main(String[] args){

int a = -5;

a >>>= 1;//a = 5 >>> 1 = 2147483645

System.out.println(a);//2147483645

}

}

(&=)位与赋值

假设值int a = 129,操作为a &= 128,具体步骤如下:

1.首先执行129 & 128的操作,结果为128

2.把结果赋值给a,则a = 128

public static void main(String[] args){

int a = 129;

a &= 128;//a = 129&128 = 128

System.out.println(a);//128

}

(|=)位或赋值

假设值int a = 129,操作为a |= 128,具体步骤如下:

1.首先执行129 | 128,结果为129

2.将结果赋值给a,则a=129

public static void main(String[] args){

int a = 129;

a |= 128;//a = 129|128 = 129

System.out.println("129|128="+(129|128));//129

}

(^=)位异或赋值

假设当前值a = 8,操作为a ^= 11,具体操作如下:

1.首先执行8 ^ 11,得到结果为3

2.将结果赋值给a,则a = 3

public static void main(String[] args){

int a = 8;

a ^= 11;//a = 8^11 = 3

System.out.println(a);//3

}

java 二进制位运算_Java中的二进制与位运算相关推荐

  1. java异或_java中异或是怎样算的

    展开全部 概述 i = 14,异或算法转换二进制,同则取0异则取1: 解析 异或是一种基于二进制的位运算32313133353236313431303231363533e58685e5aeb93133 ...

  2. python二进制移位_python学习特辑——二进制和位运算篇

    以前学习java的时候,二进制和位运算只停留在"懂"的程度,从来没有花时间去推导和总结,作为一个数学系的学生,一直想花点时间做推理证明 java和python关于二进制和位运算的规 ...

  3. 有趣的二进制—高效位运算

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇<有趣的二进制>我们讲到二进制的一些基础知识,但没有讲到位运算,有同学大呼不过瘾,那这一篇主要讲解下位运算的 ...

  4. 超有趣的二进制—高效位运算秒懂

    附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读书籍书单大全: 书单导航页(点击右侧 极客侠栈 即可打开个人博客):极客侠栈 ①[Java]学习之路吐血整理技术书 ...

  5. 单片机c语言位运算写法,单片机与嵌入式系统中C语言的位运算小记

    原标题:单片机与嵌入式系统中C语言的位运算小记 编了个PIC的项目,对里的还是蛮有感悟的,特此记录一下. 譬如说,在程序中定义了一个char类型的变量, purge_short_enable_flag ...

  6. 【CV 向】了解 OpenCV 中的算术与位运算

    文章目录 引言 1. 利用 NumPy 创建图像 2. 算术运算 2.1 加法与减法 2.2 乘法与除法 3. 位运算 3.1 与运算 3.2 或运算 3.3 异或运算 3.4 非运算 结论 引言 P ...

  7. java二进制数组_Java中的二进制及基本的位运算

    Java中的二进制及基本的位运算 二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二 ...

  8. java实现次方的运算_Java中对于位运算的优化以及运用与思考

    引言 随着JDK的发展以及JIT的不断优化,我们很多时候都可以写读起来易读但是看上去性能不高的代码了,编译器会帮我们优化代码.之前大学里面学单片机的时候,由于内存以及处理器性能都极其有限(可能很多时候 ...

  9. java取余位运算_Java中对于位运算的优化以及运用与思考

    引言 随着JDK的发展以及JIT的不断优化,我们很多时候都可以写读起来易读但是看上去性能不高的代码了,编译器会帮我们优化代码.之前大学里面学单片机的时候,由于内存以及处理器性能都极其有限(可能很多时候 ...

最新文章

  1. Labview 2017安装教程
  2. Maven基础知识--Maven资源库详述
  3. 类库 通用变量 is和as 委托
  4. OpenCV4.0-alpha发布!新增多个深度学习特性
  5. mysql常用系统函数归类
  6. 如何在linux centos下安装git(转)
  7. DayDayUp:2021年的自我总结
  8. Linux 常用命令大全(非常全!!!)
  9. to teacher eulogy
  10. java B2B2C 源码 多级分销Springcloud多租户电子商城系统-Spring Cloud eureka
  11. 合成PDF文档,合并PDF文档
  12. WIN7 旗舰版、专业版、家庭高级版32位64位官方原版下载地址
  13. 京东面试题咖啡杯问题(贪心算法、递归综合运用)
  14. c语言输入12行怎么输入,c语言中,定义什么型别的变数能同时储存数字跟字元,怎么输入...
  15. 从项目的一个 panic 说起:Go 中 Sync 包的分析应用
  16. 三子棋小游戏(经过轻微改编可变为五子棋)
  17. 当前数据中心运维管理工作中存在的问题
  18. Android MultiDex实践:如何绕过那些坑?
  19. 详解变分自编码器VAE(Variational Auto-Encoder)
  20. antd 每次打开modal 初始化数据

热门文章

  1. Python 基础教程(第二版)读书笔记
  2. SAR图像飞机目标检测识别进展
  3. C# Task阻塞方式和延续操作
  4. markdown数学类总结
  5. 控制台应用程序-打印图形
  6. CSS水平垂直居中的几种方法
  7. 孔老师智能阅卷服务器,孔老师阅卷成绩查询
  8. php获取其他网站的cookie,php获取(curl) 带有cookie的网页数据采集方法
  9. 脚本引流,什么是脚本引流?脚本引流会是骗局么?
  10. TEQC数据处理与质量分析