咱们都知道,在计算机世界里,再复杂,再美的程序,到最后都会变成0与1。也就是咱们常说的:二进制。二进制相信你们都很熟悉。与现实世界不一样的是,在现实世界里,咱们一般都是用十进制来表示的,也就是遇十进一,这些都是咱们熟悉的。到这里,咱们就会发现端倪,现实世界中的十进制与计算机中的二进制其计量单元是不同的。那它们之间怎么转换呢?这就涉及到一些比较基础的计算机知识。不在本文中讨论(若是有兴趣,能够在下次讲讲)。嗯,回到今天的主题,来讲说位运算,这又是一个怎样的概念呢?咱们从小就开始接触,现实世界中的加减乘除这些运算,也就是十进制中的运算。今天咱们要说的是:二进制位中的一些经常使用运算。例如:& (位与),| (位或) ,^(异或),<<(左移),>>(右移) 等等。程序员
在进行运算符使用以前,咱们有必要说下真假。在Java中,咱们都知道,用 true 值表示真,false 值表示假。其实在计算机中,一般使用 1 表示真,0表示假。使用过Json的同窗应该知道,Java中的boolean类型,用1也是能够反序列化成true,0反序列化为false的。算法
在说位与以前,咱们先来讲说咱们熟悉的 && 逻辑与操做。简单来讲: A&&B 也就是:A且B同时成立时为真,不然为假。也有人称之为:“一假必假”。spa
如今咱们再来看位与。首先,咱们来看一段程序:.net
@Test public void testBit(){ int a = 8; int b = 9; System.out.println("a binary: "+Integer.toBinaryString(a)); System.out.println("b binary: "+Integer.toBinaryString(b)); System.out.println("a & b binary: "+Integer.toBinaryString(a&b)); System.out.println("a & b result: "+(a&b)); }
再看解释以前,咱们先猜猜结果是多少?3d
代码解释:code
位与:咱们从字面意思上来理解,也是二进制位的与操做。blog
数字 8 的十进制是: 1000 。图片
数字 9 的十进制是: 1001。get
咱们再来进行位于操做:源码
以下所示:
8:1000 9:1001 & 8 1000
最左边的 1&1 = 1,中间的 0&0 = 0,最右边的0&1 = 0。
二进制的结果为:1000,转换为10进制后为 8。
程序运行结果以下:
a binary: 1000 b binary: 1001 a & b binary: 1000 a & b result: 8
结果是符合预期的。
上面说 & (位与) 操做,如今咱们来看看位或操做,继续使用上面的例子:以下所示:
@Test public void testBit(){ int a = 8; int b = 9; System.out.println("a binary: "+Integer.toBinaryString(a)); System.out.println("b binary: "+Integer.toBinaryString(b)); System.out.println("a & b binary: "+Integer.toBinaryString(a|b)); System.out.println("a & b result: "+(a|b)); }
再看看二进制:
8:1000 9:1001 | 9 1001
最左边的 1|1 = 1,中间的0|0 = 0 ,最右边的 0|1 = 1。
结果二进制为: 1001 对应的10进制为 9。
运算结果以下:
a binary: 1000 b binary: 1001 a & b binary: 1001 a & b result: 9
这个运算符比较有意思,异从字面上来理解是:不一样的。放在位操做里也是同样的。继续使用上面的例子:
@Test public void testBit(){ int a = 8; int b = 9; System.out.println("a binary: "+Integer.toBinaryString(a)); System.out.println("b binary: "+Integer.toBinaryString(b)); System.out.println("a & b binary: "+Integer.toBinaryString(a^b)); System.out.println("a & b result: "+(a^b)); }
继续看二进制:
8:1000 9:1001 ^ 1 0001
位相同时取假,不一样时取真。左边的 1=1 相同取假,也就是0。中间的0=0 也为假为0。最右边的0不等于1,为真。结果也就为1。
在现实世界里,咱们常常使用乘法。<< 则表示二进制中的位移操做,低位补0。例如:8<<1。
@Test public void testCode(){ int a =8; System.out.println("a toBinaryString: "+Integer.toBinaryString(a)); System.out.println("a<<1 toBinaryString: "+Integer.toBinaryString(a<<1)); System.out.println("result: "+(a<<1));
二进制以下:
8 1000 8<<1 16 10000
结果为: 2^4 = 16。 << 左边 a 表示基数, 右边 1 则表示须要位移动的位数。 箭头指向哪边,则向哪边位移。程序运行结果:
a toBiryString: 1000 a<<1 toBinaryString: 10000 result: 16
>>(右移) 与左移 << 则是相反的,高位补0 。继续上面的例子:
@Test public void testCode(){ int a =8; System.out.println("a toBinaryString: "+Integer.toBinaryString(a)); System.out.println("1>>a toBinaryString: "+Integer.toBinaryString(a>>1)); System.out.println("result: "+(a>>1) }
二进制:
8 : 1000 8>>1 4 : 0100
运行结果:
a toBinaryString: 1000 a>>1 toBinaryString: 100 result: 4
其实这里还有一个比较好记的口诀:
a>>n 则表示: a / (2^n) 次方。 (取整)
a<<n 则结果为: a * (2^n) 次方。
如今咱们来速算一下:
当a = 13, n = 2 时。13<<2 等于 13* 4 = 52 。 13/4 = 3。
(上述速算法,若有错误,欢迎打脸!!!)
咱们在源码以及常见算法中位移运算是很是常见的,一位Java程序员掌握位运算也是颇有必要的。这对咱们算法,源码理解都很是有帮助!
相关阅读:
《软件之路》
扫码关注,一块儿进步
我的博客: http://www.andyqian.com