Java运算符基础

  • 今天重温的主要是Java运算符,在这里我把之前已经遗忘的一些点记录下来,以后回顾的时候可以翻阅。

比较运算符

^异或:

  • 符号两边的结果相同为False,不同则为True
    1
    2
    3
    4
    True  ^ True  = False ;
    False ^ True = True ;
    True ^ False = True ;
    False ^ False = False ;

!非:

  • 两次非运算就是原数
    1
    2
    !true  = false ;
    !!true = true ;

逻辑运算符

&和&&的区别:

  • 让我们先来看一段代码

    1
    2
    3
    int x = 1;
    if(x>2 && x<5)
    System.out.println();
  • 在上面的情况中,在对 && 左边的式子进行判断后,得出左边的式子值是false,因为两数相与,只要有一个flase,整体式子的结果就是false。所以停止运算右侧式子,直接给出false的结果。

  • 但是使用 & 运算符的时候,无论左边式子是什么,右边都参与运算。

  • && 和 & 运算结果一样,过程有一些小区别
    & :无论左边式子是什么,右边都参与运算
    && :当式子左边为false时,右边不参与运算,结果为false

|和||的区别

  • 上面我们说了 & 和 && 的区别,其实原理是一样的
  • || 和 | 运算结果一样,过程有一些小区别
    | :无论左边式子是什么,右边都参与运算
    || :当式子左边为true时,右边不参与运算,结果为true

位运算

& 位运算

  • 下面我用一个小例子来演示

    1
    2
    3
    4
    5
    6
    7
    6 & 3 = ?
    内存中
    0000-0000 0000-0000 0000-0000 0000-0110
    & 0000-0000 0000-0000 0000-0000 0000-0011
    -----------------------------------------
    0000-0000 0000-0000 0000-0000 0000-0010
    ∴ 6 & 3 = 2
  • 6 & 3 在内存中变化的实质是,转换为2进制,各位相对应的进行 & 运算

  • 应用场景:
    取0100 0000 1100 0101的后四位,如何进行操作?
    答 :用0000 0000 0000 1111与其进行 & 运算。

| 位运算

  • 原理同上 例如 6 | 3 = 7

^ 位运算

  • 原理同上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    6 ^ 3 = ?
    内存中(简化)
    0110
    ^ 0011
    ------
    0101
    ∴ 6 ^ 3 = 5

    继续 ^ 3
    5 ^ 3 = ?
    演算后
    5 ^ 3 = 6
  • 不知道大家发没发现这个运算的一些小秘密,那就是一个数连续两次与相同的数进行异或运算后,结果会是最初的数。用公式写就是: a ^ b ^ b = a

  • 那么这个究竟可以用作干什么那?可以用于文件的加密!

~ 反码

  • 大家可以在自己的电脑上试一下下面的代码,看看是不是自己猜测的值

    1
    2
    int a = 2;
    System.out.println(~a);
  • 结果是 -3 ,很多人可能都以为反码的意思就是将a的二进制10取反为01,猜测结果是1

  • 为什么不是这样的运算过程那?
原理

这就要从计算机常用的几个码说起了。首先,java存储的是有符号数,在计算机中,有符号数通常是使用补码存储的,java也不例外。先来看看什么叫原码,反码,补码。

原码

原码就是符号位加上真值的绝对值,即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

1
[+1]原 = 0000 0001

反码

正数的反码是其本身
负数的反码是在其原码的基础上,符号位不变,其余各个位取反.
例如:

1
[+1] = [00000001]原 = [00000001]反

补码

正数的补码就是其本身
负数的补码是在反码的基础上+1。
例如:

1
[+1] = [00000001]原 = [00000001]反 = [00000001]补

分析

所以回到一开始的问题,int a = 2 a在计算机中是以补码存储的。

  • 对于2这个正数来说,补码、反码、原码都是相同的,又由于是数值型,在这里我先用八位bit来表示一下:
    1
    2
    原码:0000 0010
    反码:0000 0010

补码:0000 0010

  • 取反
    取反过程是在补码的基础上进行的,由于是按位取反,无论符号位还是数值位都要取反,所以结果如下:

    1
    取反后的补码: 1111 1101
  • 换算为值
    那么取反后的补码的实际值是多少呢?我们需要先把他转化为原码,过程如下:

    1
    反码 = 1111 1101 - 1 = 1111 1100

原码 = 反码符号位不变,其余取反 = 1000 0011

所以,最后的值-3

<< 左移

  • 这个符号之前并没有听说过,在这次学习中进行了掌握(开始我还以为是C++的cout那)

    1
    2
    3
    4
    5
    6
    3 << 2 = ?
    内存中
    0000-0000 0000-0000 0000-0000 0000-0011
    结果
    0000-0000 0000-0000 0000-0000 0000-1100
    ∴ 3 << 2 = 12
  • 上面的运算实质是 3的2进制 整题左移两位,多余的舍弃,空位用0补

  • 一个数进行左移运算时,左移n位,即是该数乘以2的n次幂

>> 右移

  • 原理几乎一样,只有略微的不同
    原来最高位是什么,用什么补空位(因为最高位为1时是负数)
  • 右移n位,即是该数除以2的n次幂
    1
    2
    3
    4
    -12 >> 2 = ?
    答: -3
    12 >> 2 = ?
    答: 3

>>> 无符号右移

  • 高位空位,全部填0,用0补位
    1
    2
    3
    4
    -12 >>> 2 = ?
    答: 3
    12 >>> 2 = ?
    答: 3

应用

  • 请用效率最高的方法求出 2*8 的值。

    1
    System.out.println(2<<3);
  • 两个整数值互换(不使用第三方变量)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    方法1:(不建议使用,如果数值过大,可能丢失精度)
    int a = 3, b = 5;
    a = a + b;
    b = a - b;
    a = a - b

    方法2:(利用异或位运算)
    int a = 3, b = 5;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;

三元运算符

  • (条件表达式)?表达式1:表达式2
  • 若条件为true ,结果为表达式1
    若条件为false,结果为表达式2
    1
    2
    3
    4
    练习:在x , y中取 值较大的整数
    int x = 3, y = 4;
    int max = ( x>y )? x : y;
    System.out.println(max);

swich 和 if else 与 三元运算符

  • 三元运算符必须有结果,if else可有,可不有结果。当if else有具体运算结果时,可以使用三元运算符。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    swich使用示范:
    int x = 3;
    swich(x)
    {
    case 1:
    System.out.println(x);
    break;
    case 2:
    System.out.println(x);
    break;
    case 3:
    System.out.println(x);
    break;
    case default:
    System.out.println(x);
    break;
    }
  • if:

    对几个具体值进行判断
    对区间判断
    对运算结果boolean类型表达式判断
    

    swich:

    对几个具体值进行判断
    值的个数通常是固定的
    
  • 对几个固定值判断,建议使用swich,swich将答案存在内存中,效率高