运算符(上)

算术运算符

  +、-、*、/、%(取余)

        int a =3;
        
        int b =0;
    
        b=a/2; //需注意b是整型,3/2的值是1
        //------------------------------------------------------- 
        int a = 4;

        int b =0;

        b=a%2;  //a%2,求的书4/2的余数,为0                    

赋值运算符

  = 、+=、 -=、 /=、 *=、%=

    int x=1;    //把1赋给变量x
    
    x+=1;      //类似于:x=x+1;
    
    //--------------------------------------------------------
    byte x =1;

    x += 2;                  //+=类似于=,等号右边是常数,自动类型转化

    int y =1;

    byte b =0;               

    y += b;                  //+=类似于=,等号右边是常数,自动类型转化 
    
    x = (byte)(x+2);  //不加byte编译报错,类型从int转化为byte可能有损失,可以看成等于右边为一个表达式,不做自动转化

 关系运算符

  >、<、>=、<=、==、!=、instanceof(用于比较一个对象是否属于一个类型)

   关系运算符的结果为Boolean类型

逻辑运算符

  &&(短路与)、&(逻辑与)、||(短路或)、|(逻辑或)、!(非)、^(逻辑异或)

  短路与与逻辑与的区别在于,当第一个条件为假时,短路与会发生短路,后面的不执行,逻辑与不论是真还是假都会执行到最后;

  短路或与逻辑或的区别在于,当第一个条件为真时,短路或会发生短路,后面的不执行,逻辑或不论是真还是假都会执行到最后

  短路与和短路或在发生短路的情况下,性能才比逻辑与或者逻辑或更高

  (3>1)^(3<2):前后两个表达式结果不同,那么最终结果为true,反之为false

位运算符

  进制转换(扩展):

    十进制转二进制:除2直到商为1,将余数倒序排列

运算符(上)

 

 

 

 

 

 

 

 

 

    二进制转十进制:每个元素乘以2的位数-1,求和   

00000100   0*27 + 0*26+0*25 + 0*24 + 0*23 + 1*22 + 0*21 +0*20 = 4

    八进制:以3个bit为一组,把每一组计算成十进制,开头加上数字0,作为标记。

运算符(上)

    16进制:以4个bit为一组,把每一组用二进制转十进制的方式方式,计算每一组的数,有些不同的是,10到15的数字,分别依次用A、B、C、D、E、F表示,开头加上0x(数字0,不是字母o),作为标记。

0010 1110

 2  E

16进制:0x2E

    &(按位与)、 |(按位或)、^(按位异或)、~(按位取反)、<<(按位左位移)、>>(按位右位移)、>>>【按位右位移(无符号)】

    按位与运算,类似于把1看成真,0看成假,只有对应bit的数都为1,该bit结果才为1,其他都为0

9 & 1 == 1

00001001

00000001 

00000001     

    按位或运算,类似于把1看成真,0看成假,只要对应bit位上有1,该bit结果才为1,其他为0 

9 | 1 == 9

00001001

00000001 

00001001 

    按位异或,类似于把1看成真,0看成假,当对应bit位上两个数不一样,该bit结果为1,其他为0

9 ^ 1 == 8

00001001

00000001

00001000

    按位取反,在这,我们需要知道计算机中无论是正数还是负数,其在内存中的存储形式都是一补码的形式存储的,其中,正数的原码、反码、补码都是一样的(下面的二进制数也可以用 符号位+有效位 来代替 ,如 9的原码----—> 01001)

9

原码:00000000 00000000 00000000 00001001

反码:00000000 00000000 00000000 00001001

补码:00000000 00000000 00000000 00001001

-9

原码:10000000 00000000 00000000 00001001

反码:11111111 11111111 11111111 11110110(符号位不变,其余取反)

补码:11111111 11111111 11111111 11110111(反码+1)

~9 == -10

9的补码:                  00000000 00000000 00000000 00001001

取反:                     11111111 11111111 11111111 11110110

-1(因为求的是负数的原码):           11111111 11111111 11111111 11110101

“取反后的数”的原码(符号位不变,其余取反): 10000000 00000000 00000000 00001010

    看起来有点绕,可以这样认为:找到了9的补码,先将9的补码取反(可以把它看成~9),再 - 1,最后符号位不变,其余取反(后面两步类似于求一个负数的补码的逆过程,是把取反后的数,这个数可看成你要求的数的补码,将这个数的补码转成原码的形式)

    负数和正数的过程也差不多

~(-9) ==8

-9的补码:                      11111111 11111111 11111111 11110111

取反:                        00000000 00000000 00000000 00001000

“取反后的数”的原码(正数的原码、反码、补码相同):   00000000 00000000 00000000 00001000

    按位左位移

6 << 2 == 24

00000000 00000000 00000000 00000110

类似于在之前的最右边加位移个数(即上面“6 << 2 ”的2)的0(无论正数还是负数),再把最左边的位移个数的数去掉(符号位不动,即去掉符号位之后的)

00000000 00000000 00000000 00011000

    也先相当于,乘以2的位移次幂,即6 * 22 = 24

-6 << 2 == -24

-6的补码:        11111111 11111111 11111111 11111010

按位左位移运算:     11111111 11111111 11111111 11101000

符号位不变,其他位,取反:11111111 11111111 11111111 00010111

+1:           1000000 0000000 0000000 00011000    

    按位右位移

6 >> 1 == 3

00000000 00000000 00000000 00000110(6的补码)

类似于在之前的最右边减掉位移个数(即2)的0或1,在最左边加上位移个数的数的0(正数)或1(负数)(符号位不动,即类似于在符号位后加)

00000000 00000000 00000000 00000011

也先相当于,除以2的位移次幂,即6 / 21 = 3

-6 >> 1 == -3

-6的补码:          11111111 11111111 11111111 11111010

按位右位移运算:       11111111 11111111 11111111 11111101

符号位不变,其他位,取反:  10000000 00000000 00000000 00000010

+1:             10000000 00000000 00000000 00000011

     所以,我们再做一些乘除法运算时,可以利用这些来做,提高计算机的计算效率

 -6 >>> 1 == 2147483654

11111111 11111111 11111111 11111010(-6的补码)

类似于在之前的最右边砍掉位移个数的0或1(不考虑符号位,无论正数还是负数都直接在最左边补0)

011111111 11111111 11111111 1111101

 注意

    位运算是用补码来进行的,正数的三码都一样,负数的三码是有区别,在&、|、~、<<、>>、>>>,中如果是负数的位运算,需要注意这一点  

上一篇:Windows内核 TSS任务段


下一篇:Java 高并发与多线程;:synchronized 关键字的实现原理