java两个整数做/运算的结果也是整数的。
Java支持+=、-=、/=、*=、%=等写法。 Java支持C风格的自增自减。
移位运算可以看我的另一篇文章,讲的很详细。廖雪峰老师这点讲得不好。
位运算是按位进行与、或、非和异或的运算。(即对应位进行这些运算)
n = 0 & 0; // 0 n = 0 & 1; // 0 n = 1 & 0; // 0 n = 1 & 1; // 1 ------------------- n = 0 | 0; // 0 n = 0 | 1; // 1 n = 1 | 0; // 1 n = 1 | 1; // 1 ------------------- n = ~0; // 1 n = ~1; // 0 ------------------- n = 0 ^ 0; // 0 n = 0 ^ 1; // 1 n = 1 ^ 0; // 1 n = 1 ^ 1; // 0 -------------------与:全1为1. 或:有1为1. 非:取反 异或:相异为一
对两个整数进行位运算,实际上就是按位对齐,然后依次对每一位进行运算。
位运算在处理某些场景时威力巨大。而且位运算效率极高。
先说什么时候用:可以方便的对某些数据进行筛选。 if ((skill & mask) == mask) 是典型的位运算检查,它要求的是mask上为1的位,skill上也为1。 比如检查电话号码,你想找出来1324016这个号段的所有号码,怎么办?难道要对每个电话号码先转成字符串,判断一下前七位是不是1324016嘛?太low了。
final int TARGET_NUMBER = 13240160000; for(int i = 0; i < arr.length; ++i){ if((TARGET_NUMBER & arr[i]) == TARGET_NUMBER){ // do something. } }同样,如果说要筛选出具有某些共同特征的数据,那么就要考虑一下与运算了。
脑洞再开,与运算既然是都是1,结果才是1,那么好像可以用来判断某位数字是不是1啊?(个位是不是1可以用来标识是奇数还是偶数)
所以日后判定奇偶数可以这么写:
if((target&1) > 0){//是奇数} else{//是偶数}说到异或,骚操作就更多了。 参考了下某大神的博客,请尊重原创!
异或的性质:
交换律结合律自反性好玩的特性自反性:异或同一个数两次,得到的还是自己。
A^b^b == A //true好玩的特性:
a^a == 0 //true a^0 == a //true根据这几个好玩的特性,我们可以有很多效率极高的骚操作。
0x00:不引入第三个变量进行数值交换(不能用python序列解包)
a = a^b; b = a^b; a = a^b;0x01:找出重复的数 有个长度为1001的数字,存储了1-1000的数字,其中有一个数字出现了两次,其余数字均出现了一次,怎么找出来?不能用额外的存储空间。
首先,不能用额外存储空间就代表不能用hash的办法来做。set,map都不能行了。 然后我们想到可以把整个数组中所有数字都加起来求和,减去1-1000的和,就可以了。这样我们要做999+1次加法运算+1次乘法运算+1次除法运算+1次减法运算。 这样看运算量对于计算机来说并不大,但是请注意一点,现在是1000的数据量,如果是1万呢?10万呢?这不就溢出了?
我们可以用异或。根据好玩的特性,我们可以用原数组中的元素去与1-1000进行异或,这样的话所有不重复的数字异或后会变成0,最后剩下的就是待查找的值,这样的话不用担心溢出,而且效率也挺好的。
0x02:找数组中只出现一次的值 这是道leetcode上的题目。用异或的自反性很容易就解决了。
自动提升规则: 你可能会对以下代码的输出感到疑惑:
package program; public class Main{ public static void main(String[] args){ char c = 'a' + 1; System.out.println(c); } }输出:
b这是咋回事儿呢?因为在java中,char的存储本质上是存储的数字。所以直接另 char = 97,也不会有什么问题。 在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。
也可以用强制类型转换:
int i = 12345; short s = (short) i; // 12345请注意与python的写法是反着的。是把关键字括了起来。
强制类型转换直接trop掉高位字节,所以有可能会出现奇奇怪怪的结果。