注:
- 参考《java核心技术 卷一 》
- 参考 http://blog.csdn.net/xiaochunyong/article/details/7748713
- 参考 http://nassir.iteye.com/blog/1994914
基本的运算符
加减乘除,+ - * /,由于java作为强类型,如果整型相乘除最终的结果还会是整型,而不是得到浮点类型,如果是浮点跟整型相整除会得到浮点:
15/2 //7
15%2 //1
15.0/2 // 7.5
自增自减运算符
这类运算符,++n或者–n会在表达式执行之前执行,而n++还有n–会在表达式执行之后执行
int m = 7;
int n = 7;
int a = 2 * ++m; //这里先执行++m 7 > 8,然后2*8最终结果为16
int b = 2 * n++; //这里先执行2 * 7结果为 14,然后在n++,n的新值是8
书中也是不要建议将自增自减运算符写到表达式里面去这样非常容易产生困惑,但是!这个但是很关键,很多大厂或者网上的面试题,就经常喜欢这样出题,出在表达式里面自增自减,然后很长一个表达式来混淆开发者们,所以这里还是需要理解写在表达式里面该如何处理,而在真正开发的时候切忌如此使用!
关系运算符与布尔运算符
各种关系运算符,==、!=、>、<、>=、<=、&&、||,使用这些关系运算符最后将返回一个boolean值,来配合条件语句来使用。
Boolean confirm = 1 == 1; //true
Boolean confirm2 = 2 < 1; //false
位运算符(重点讲解)
在处理整形术只是,可以直接对组成整型数值的各个位进行操作,位运算符包括:
&、|、^、~、>>、<<、>>>
书中对位运算符的介绍少之又少,工作中的运用也是少之又少,确实是没错,大多数的计算只需要用我们生活中平常的加减乘除就可以达到了,大部分算法也是,但是我并不认为这些方法你就可以直接忽视这些方法,因为位运算符如果使用得当,性能可以得到很快的提升它比普通的十进制的计算快一些,当项目越来越庞大,你每一百行代码提升的一点点微小性能,也对后面整个庞大的项目得到巨大的提升,所以这一章,我们重点来讲一讲这个位运算符。
1、左移( << )
System.out.println(5 << 2); // 结果是20
这里的程序是如何执行的呢,是先将5转换成二进制,然后在最后补上两个零,来这里我们先学习一下十进制转换成二进制的计算:
十进制转换成二进制的计算是,用这个十进制的数除以2得到的商在继续除以2一直除到除数只剩0为止,期间产生的余数组合就是所得到的二进制(PS:你这语言表达能力也敢出来写blog,误人子弟了你负责啊。-_-,额,我们继续):
n=x2 n = x 2 ……余数
我们继续拿例子中的5来举例
2=52 2 = 5 2 ……1
1=22 1 = 2 2 ……0
0=12 0 = 1 2 ……1
然后5就转成了二进制101了。所谓的二进制就是只有0和1组成的数,十进制就是0到9,同理八进制、十六进制。算是算完了但是这个左移动还没讲完呢,java里面int类型默认是32位的,也就是实际上是我们得到的二进制数应该是:
0000 0000 0000 0000 0000 0000 0000 0101 //这么多零别数了,一组四个,八组,我一定不骗你(虽然我自己都忘记数了)
0000 0000 0000 0000 0000 0000 0001 0100 //然后左移2就是将整个101往左边移动两位这样就变成了10100
然后得到了10100怎么办,当然是转会十进制了(舞草这么麻烦,怪不得不常用),二进制转换成十进制就是每一位(从低位到高位,也就是从右到左)的位数乘以2的当前次数幂(应该没有绕晕吧),请看公式:
a∗2n=z a ∗ 2 n = z
我们继续拿之前转换之后的101举例
1∗20=1 1 ∗ 2 0 = 1
0∗21=0 0 ∗ 2 1 = 0
1∗22=4 1 ∗ 2 2 = 4
然后 1 + 0 + 4 = 5 就得到我们之前的5了,然后我们计算新值10100(从右到左)如下:
0∗20=0 0 ∗ 2 0 = 0
0∗21=0 0 ∗ 2 1 = 0
1∗22=4 1 ∗ 2 2 = 4
0∗23=0 0 ∗ 2 3 = 0
1∗24=16 1 ∗ 2 4 = 16
然后结果是0 + 0 + 4+ 0 + 16 = 20;
所以5 << 2的结果是20,计算了那么多,等后面我们学习了方法,将这些方法封装起来就可以供我们重复使用了,但是这些方法到底有什么用呢(其实我也很少用,可能实际场景真的用的太少,不应该说我太水,然后我谷歌了半天得到了一句话):利用位运算存储数据,主要是为了减少程序占用的内存。位运算的计算速度快,占用资源少。咳,虽然计算的时候对于我们相关计算的时候稍微有一些难度,但是现实中如果能用得好,就能得到很多计算的便利,你只要相信这是通往大神的道路(额扯远了,我们继续)
2. 右移 (>>)
同理左移
5 >> 2 // 1
0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0001 //后面的01移出去了就没了
```3. 无符号右移(>>>)
说道符号,前面十进制转换二进制的计算里面并没有说道符号,这里具体讲解一下,如果是-5如何转换成二进制,其实还是先通过求出5的二进制之后,然后将每一位取反,然后在加1补位即可。
<div class="se-preview-section-delimiter"></div>
0000 0000 0000 0000 0000 0000 0000 0101
1111 1111 1111 1111 1111 1111 1111 1010 //这个是反码,然后再加1,变成补码
1111 1111 1111 1111 1111 1111 1111 1011 //这个就是-5的表示方法
同理将二进制转换成十进制的负数就是,当二进制码的最高位为1的时候,就是负数,第一步就应该先想每一位取反补1,之后在进行二进制到十进制的计算
<div class="se-preview-section-delimiter"></div>
1111 1111 1111 1111 1111 1111 1111 1011 //还是拿这个-5举例 由于第一位是1
0000 0000 0000 0000 0000 0000 0000 0100 //先取反
0000 0000 0000 0000 0000 0000 0000 0101 //然后补1 在计算成十进制在补上符号即可
然后继续用-5>>3:
<div class="se-preview-section-delimiter"></div>
-5 >> 3
1111 1111 1111 1111 1111 1111 1111 1011 //-5
1111 1111 1111 1111 1111 1111 1111 1111 //这里发生了什么!就是前面补了三个1,由于是负数,所以这里用1来补位,所以通过计算这个最后得出的结果是-1
我们计算 -5 >>> 3:
<div class="se-preview-section-delimiter"></div>
-5 >>> 3 //无符号右移,什么是无符号,我认为就是不管是不是正数还是负数,在前面补零就行了
1111 1111 1111 1111 1111 1111 1111 1011 // -5
0001 1111 1111 1111 1111 1111 1111 1111 //就这样,然后在计算一下最终的结果即可,最终结果是536870911
总结一下:
就是右移,正数高位用0补位,负数高位用1补位,切忌只是右移;而左移的话低位只是补零无论正数还是负数。而无符号右移自然而然就变成了正数因为是补零,啥为什么没有无符号左移动,前面不是说了,左移动都是低位补零,所以有没有符号都一样对吧。
4. 位与(&)
<div class="se-preview-section-delimiter"></div>
5 & 3 //结果为1,先将两个都转为二进制,在进行比较
0000 0000 0000 0000 0000 0000 0000 0101 //5
0000 0000 0000 0000 0000 0000 0000 0011 // 3
0000 0000 0000 0000 0000 0000 0000 0001
//1 ,这里就是比较每一个相同的位置,都为1的就为1,否则其他情况都为0
5.位或(|)
同理&,反之就是,我们也依旧看一下
<div class="se-preview-section-delimiter"></div>
5 | 3 //结果为1,先将两个都转为二进制,在进行比较
0000 0000 0000 0000 0000 0000 0000 0101 //5
0000 0000 0000 0000 0000 0000 0000 0011 // 3
0000 0000 0000 0000 0000 0000 0000 0111
//7 ,只有有一个位置是1那就是1
6. 位异或(^)
<div class="se-preview-section-delimiter"></div>
5 ^ 3 //结果为1,先将两个都转为二进制,在进行比较
0000 0000 0000 0000 0000 0000 0000 0101 //5
0000 0000 0000 0000 0000 0000 0000 0011 //3
0000 0000 0000 0000 0000 0000 0000 0110
//6 ,互为相反则为1,相同则为0
7.位非( ~ )
这玩意看起来最简单,就是取反
<div class="se-preview-section-delimiter"></div>
~5 //-6
0000 0000 0000 0000 0000 0000 0000 0101 //5
1111 1111 1111 1111 1111 1111 1111 1010 //-6
“`
写了好多,不知道总结到位了没有,其实就是想完善的总结了这一些位运算符的常见用法吧,毕竟我们平时可能忽略得非常多,但是如果运用得当可以给项目带来非常大的提升,有时候高手都处于细节,希望也有人能看到我这篇blog能学到更多的东西。