运算符

发布时间 2023-09-09 11:54:27作者: SimpleWord
title: 运算符
index_img: https://picss.sunbangyan.cn/2023/07/30/stdtw2.jpg
tags:
  - Java SE
categories:
  - Java SE
hide: false
excerpt: 运算符、类型转换、原码、反码、补码。

算数运算符

+、-、*

public class Main {
    public static void main(String[] args) {
        System.out.println(1 + 3); // 4
        System.out.println(2 + 1.1); //3.1
        System.out.println(1.1 + 1.3);//2.4000000000000004

        System.out.println(2 * 3); //6
        System.out.println(2 * 1.3); //2.6
        System.out.println(3.1 * 2.2);//6.820000000000001
    }
}

字符的+

  • 字符会转为ASCII表中的对应数字
    • 字符+数字
    • 字符+字符
  • 字符+字符串,这是字符串拼接
public class Main {
    public static void main(String[] args) {
        System.out.println(1 + 'a' + 1); //99
        System.out.println('a' + 'b'); //195
        System.out.println(1 + 'a' + 'b' + 1); //197
        System.out.println('a' + "bc"); //abc
    }
}

字符串的+

  • +运算中出现字符串,此时的两个数间+不再是算数运算符了,而是字符串拼接操作

  • 连续+则从左到右执行

public class Main {
    public static void main(String[] args) {
        System.out.println(12 + 23); //25
        System.out.println(12 + "23"); //1233
        System.out.println(1 + 2 + 3 + "4" + "5"); //645
        System.out.println("123" + true); // 123true
        System.out.println(1 + 2 + "abc" + 2 + 1); //3abc21
    }
}

/

public class Main {
    public static void main(String[] args) {
        System.out.println(10 / 2); // 5
        System.out.println(10 / 3); //3
        System.out.println(10.0 / 5); //2.0
        System.out.println(10.0 / 3); //3.3333333333333335
    }
}
  • 类型不同,不能参与运算,需要类型转换,上方的例子发生了隐式转换
  • 小数参与运算得到的结果可能不正确

%

用于执行取余操作。语法是a % b

%运算符只可用于整型的操作数,包括intlongbyteshort

public class Main {
    public static void main(String[] args) {
        System.out.println(10 % 2); //0
        System.out.println(17 % 3); //2
        System.out.println(-13 % 4);//-1
    }
}

案例

获取各个数

提取一个整数 num 的倒数第 k 位数字:\(num/10^{k-1}\%10\)

public class Main {
    public static void main(String[] args) {
        int num = 3456;
        byte k = 3;
        int result = num / (int) Math.pow(10, k - 1) % 10;
        System.out.println(result); // 4
    }
}

类型转换

不同的数据类型不能直接计算。

隐式转换

类型小的会自动转为类型大的再参与运算。(联系下方原反补)

规则:自动补0,直到字节对齐。

byteshortchar只要参与运算都会直接提升为int,再计算。

public class Main {
    public static void main(String[] args) {
        byte a = 10;
        short b = 11;
        long k = 10;
        long result = a + b + k;
        //首先a和b都要转换为int运算,然后结果转换为long与k运算,结果是long类型
    }
}

强制转换

规则:自动删除前面字节,直到字节对齐。(联系下方原反补)

格式:目标类型 变量名 = (目标类型) (被强转的数据)

强转可能结果会“错误”

public class Main {
    public static void main(String[] args) {
        byte a = 10;
        short b = 11;
        byte result = (byte) (a + b);
        System.out.println(result); //21 且是byte类型,a+b的结果是int
    }
}
public class Main {
    public static void main(String[] args) {
        int a = 200; // 补码(4字节):0000 0000 0000 0000 0000 0000 1100 1000
        byte b = (byte) a;  // 补码(1字节,去除前面3字节) 1100 1000
        System.out.println(b); // 回推原码返回:0011 1000=-56
    }
}

自增自减

不参与运算

单独占一行,都是原来的加或减1

public class Main {
    public static void main(String[] args) {
        byte a = 10;
        System.out.println("a:" + a); //10
        a++;
        System.out.println("a:" + a); //11
        a--;
        System.out.println("a:" + a); //10
        a++; //11
        a--; //10
        System.out.println("a:" + a); //10
    }
}

参与运算

  • b=a++;先用(赋值)再++

  • b=++a;先++再用(赋值)

public class Main {
    public static void main(String[] args) {
        int a = 10;
        int b = a++; //b=10,a=11
        int c = ++a; //a=12,c=12
        System.out.println("a:" + a); //12
        System.out.println("b:" + b); //10
        System.out.println("c:" + c); //12

        int d = a++ + ++b - a--;
        /*
            相当于:d=x+y-z
            x=a++,即x=12,a=13
            y=++b,即y=b=11
            z=a--,即z=13,a=12
            d=12+11-13
         */
        System.out.println("a:" + a);//12
        System.out.println("b:" + b);//11
        System.out.println("d:" + d);//10
    }
}

赋值运算符

符号 说明 使用
= 左右相等 \(a=b\)
+= 先+再赋值 \(a+=b\)
*= 先*再赋值 \(a*=b\)
/= 先/再赋值 \(a/=b\)
%= 先%再赋值 \(a\%=b\)

+=,、*=,/=,%=

  • a+=ba=a+b不相等,此类运算都发生了自动强制转换
  • 强转的类型取决于左边
public class Main {
    public static void main(String[] args) {
        int a = 10;
        long b = 11;
        a += b;
        System.out.println(a); //21
    }
}

反编译如下,可以看到强转

public class Main {
    public Main() {
    }

    public static void main(String[] var0) {
        int var1 = 10;
        long var2 = 11L;
        var1 = (int)((long)var1 + var2);
        System.out.println(var1);
    }
}

关系运算符

符号 说明
== 判断是否相等,成立则true,否则false
!= \(\dots\)
> \(\dots\)
< \(\dots\)
\(\ge\) \(\dots\)
\(\le\) \(\dots\)

关系运算符的结果都是boolean类型

public class Main {
    public static void main(String[] args) {
        System.out.println(1 == 2); //false
        System.out.println('a' != 7); //true
        System.out.println('a' != 97); //false
    }
}

逻辑运算符

联系下方原反补深入了解。

符号 说明
& 两边都true则true
| 一边true则true
! 取反
^ 相同为false,否则true
public class Main {
    public static void main(String[] args) {
        System.out.println(true & false); //false
        System.out.println(true & true); //true
        System.out.println(!true); //false
        System.out.println(true ^ true); //false
        System.out.println(true ^ false); //true
    }
}
符号 说明
&& 与&功能相同,但左边为false则不再判断右边
|| 与|功能相同,但左边为true则不再判断右边
public class Main {
    public static void main(String[] args) {
        int a = 1;
        int b = 1;
        System.out.println(a == 2 && (b++) == 2); //false
        System.out.println(b); // 1
    }
}

三元运算符

格式:关系表达式?表达式1:表达式2;

结果必须被使用,如果true,则结果是表达式1,否则是表达式2

public class Main {
    public static void main(String[] args) {
        String result = 3 > 5 ? "结果是true" : "结果是false";
        System.out.println(result); //结果是false
    }
}

原码、反码、补码

原码

符号位(2)+数值二进制(7)

  • 0为+,1为-

  • 最大值: 0 1111111即+127

  • 最小值:1 1111111即-127

直接用原码做正数运算不会出错。

  • 如1+2

  • 0000 0001 +0000 0010=0000 0011=3

做负数运算会出错

  • 如-1+2

  • 1000 0001+0000 0010 =1000 0011 =-3

反码

解决原码不能计算负数的问题

规则

  • 正数的反码与原码相同
  • 负数的反码在原码的基础上,符号位不变数值取反

正常情况

  • 如-4-1
  • 反码-1:1111 1011 - 0000 0001=1111 1010
  • 反码回推原码:1000 0101=-5

异常情况(跨0会产生“1”误差)

  • 如-0+1
  • 反码+1: 1111 1111 + 0000 0001=0000 00000=+0
  • 误差来源:0有+0和-0两种形式

补码(计算和存储采用的形式)

解决反码的误差问题

规则

  • 正数的补码与原码相同。
  • 负数的补码是其反码加1

按照规则,0只有一种形式

  • +0:0000 0000
  • -0: 0000 0000

跨0计算

  • 如-4+2
  • 补码+2:1111 1100 + 0000 0010=1111 1110
  • 补码回推(符号位)原码:1000 0010 = -2

-128补码

  • 10000 0000=-128

计算机计算和存储采用补码,一个字节的范围是-128~127,打印时通常以十进制还原给我们。