Java 笔记 2: 进制,运算符,交换变量值的三种方法

进制

进制的分类

十进制:
数字范围:0-9
进位规则:逢十进一
二进制:
数字范围:0-1
进位规则:逢二进一
八进制:
数字范围:0-7
进位规则:逢八进一
十六进制:
数字范围:0-9、A-F(或者a-f)
进位规则:逢十六进一

	十进制	二进制	八进制	十六进制

0 0 0 0 0
1 1 1 1 1
2 2 10 2 2
3 3 11 3 3
4 4 100 4 4
5 5 101 5 5
6 6 110 6 6
7 7 111 7 7
8 8 1000 10 8
9 9 1001 11 9
10 10 1010 12 A
11 11 1011 13 B
12 12 1100 14 C
13 13 1101 15 D
14 14 1110 16 E
15 15 1111 17 F
16 16 10000 20 10
。。。。

25 25 11001

本质上,就是生活中的十进制,和计算机世界中的二进制
因为在计算机中二进制数字太长了,在代码中去表示二进制很繁琐,
那么引入了八进制和十六进制,为了快速和简短的表示二进制

(1)十进制–>二进制
(2)二进制–>八进制
把二进制从最右边开始,三位一组
(3)二进制–>十六进制
把二进制从最右边开始,四位一组

在程序中如何表示某个数字是十进制、二进制、八进制、十六进制

十进制,正常写
二进制,在数字前面加0B或0b
八进制,在数字前面加0
十六进制,在数字前面加0X或0x

为什么byte类型的范围是-128~127?

byte是1个字节,1个字节是8位
计算机中是使用“补码”的形式来存储数据的,为了理解/换算“补码”,我们在引入“原码、反码”。
规定:正数的原码、反码、补码三码合一;
负数的原码、反码、补码是不同的。
因为计算机中把最高位(最左边的二进制位)定为符号位,0表示正数,1表示负数。

25:
原码:0001 1001
反码:0001 1001
补码:0001 1001
-25:
原码:1001 1001
反码:1110 0110 符号位不变,其余位取反(0变1,1变0)
补码:1110 0111 在反码上加1

正0: 0000 0000

正数:
0000 0001 : 1
|
0111 1111 : 127
负数:补码
1000 0001 : 补码(1000 0001)-》反码(1000 0000)–》原码(1111 1111) -127
|
1111 1111 : 补码(1111 1111)-》反码(1111 1110)–》原码(1000 0001)-1

负0:1000 0000 如果用它表示负0,就浪费了,所以用它来表示其他的数
-127的二进制的补码:1000 0001
1的二进制的补码:0000 0001
-127 - 1 = (补码:1000 0001)-(补码:0000 0001) = 补码(1000 0000) = -128
计算机中用符号位来表示正、负,就是为了底层设计的简化,让符号位也参与计算。

浮点型的float和double在底层如何存储?

计算机中只有二进制?
那么如果存储3.14?
小数涉及:(1)整数部分(2)小数部分(3)这个.(4)正负号

化繁为简:
1、小数–>二进制:
(1)整数部分:除2倒取余
(2)小数部分:乘2取整数部分
3.14==》11.00100…
2、把这个二进制用科学记数法表示
1.1 00100… * n的1次方
用科学计数法表示后,对于二进制的科学计数法,整数部分永远是1,那这样的话,
整数部分就不用存了,小数点也不存了

只要存三个内容:(1)正负号(2)挪完后的几次方,指数(3)二进制的小数部分(称为尾数)
float:4个字节,就被分为三个部分,最高位还是符号位,接下来的8位用来存指数部分,然后剩下的存尾数,额如果存不下的尾数,就舍去了
double:8个字节,就被分为三个部分,最高位还是符号位,接下来的11位用来存指数部分,然后剩下的存尾数,额如果存不下的尾数,就舍去了

了解:
(1)浮点类型不精确,因为十进制的小数部分转二进制会需要舍去
(2)float类型的4个字节能表示的数字范围比long类型的8个字节还要大
因为浮点型底层存的是指数

基本数据类型之间的转换:

(1)自动类型转换
①把存储范围小的类型的值赋值给存储范围大的类型的变量,自动可以完成升级
byte->short->int->long->float->double
char->
②boolean不参与
③byte,short,char如果进行算术运算都会自动升级为int

(2)强制类型转换
①把存储范围大的类型的值,赋值给存储范围小的类型变量时,需要强制类型转换
double->float->long->int->short->byte
->char
强制类型转换是有风险的:可能会溢出或损失精度
②boolean不参与
③当需要把某个存储范围小的变量强制提升为存储范围大的类型时,也可以使用强制类型转换

public static void main(String[] args){
		/*
		从左边看d1是double类型
		从右边看10是int类型
		int类型的值,赋值给了double类型的变量,那么它会自动升级为double
		*/
		double d1 = 10;
		System.out.println("d1 = " + d1);
		
		
		/*
		从左边看i1是int类型
		从右边看10.0是double类型
		double类型的值,赋值给int类型的变量,如果直接赋值会报错:错误: 不兼容的类型: 从double转换到int可能会有损失
		*/
		//int i1 = 10.3;
		int i1 = (int)10.3;
		System.out.println("i1 = " + i1);
		
		byte b1 = 127;
		byte b2 = 2;
		//byte b3 = b1 + b2;//报错:不兼容的类型: 从int转换到byte可能会有损失,因为byte+byte就自动升级为int
		byte b3 = (byte)(b1 + b2);
		System.out.println("b3 = " + b3);
		
		short s1 = 1;
		short s2 = 2;
		//short s3 = s1 + s2;//short+short会自动升级为int
		short s3 = (short)(s1 + s2);
		System.out.println("s3 = " + s3);
		
		char c1 = '0';//'0'的编码值是48
		char c2 = '1';//'1'的编码值是49
		//char c3 = c1 + c2;//char+char会自动升级为int
		char c3 = (char)(c1 + c2);
		System.out.println("c3 = " + c3);//'a'
		
		boolean flag = true;
		//int num = (int)flag;//不兼容的类型: boolean无法转换为int
		
		int x = 1;
		int y = 2;
		System.out.println("x / y = " + x/y);//整数/整数,结果还是整数,只保留整数部分
		System.out.println("x / y = " + (double)x/y);//把x的int类型先强制升级为double类型
		
	}
	public static void main(String[] args){
		char c1 = '0';
		char c2 = '1';
		
		/*
		c1 + c2,按照求和运算,char + char结果是int
		""代表空字符串,
		当int的97与""进行 “+”拼接,结果还是97的字符串
		*/
		System.out.println(c1 + c2 + "");//97
		
		/*
		"" + c1,按照“拼接”运算,字符串 + char,结果是字符串,结果是"0"
		"0" + c2,按照“拼接”运算,字符串 + char,结果是字符串,结果是"01"
		*/
		System.out.println("" + c1 + c2 );//01
		
		/*
		c1 + "",按照“拼接”运算,char + 字符串 ,结果是字符串,结果是"0"
		"0" + c2,按照“拼接”运算,字符串 + char,结果是字符串,结果是"01"
		*/
		System.out.println(c1 + "" + c2 );//01
	}

运算符

1、算术运算符
加:+
减:-
乘:*
除:/
特殊:整数/整数,结果只保留整数部分
取模(取余):%
特殊:只看被模数的正负号
被模数%模数

正号:+
负号:-

自增:++
对于自增变量本身来说,都会+1.
但是++在前还是在后,对于整个表达式的计算来说是不一样的。
++在前,先自增,然后取自增后变量的值,
++在后,先取变量的值,然后变量自增。
但是不管怎么样,自增变量的取值与自增操作一前一后一定是一起完成的。
自减:–
类同自增

```
	public static void main(String[] args){
	int x = 10;
	int y = 3;
	
	//System.out.println("x + y = " + x + y);//变为拼接
	System.out.println("x + y = " + (x + y));
	System.out.println("x - y = " + (x - y));
	System.out.println("x * y = " + (x * y));
	System.out.println("x / y = " + (x / y));
	System.out.println("x % y = " + (x % y));
	
	System.out.println("----------------------------------");
	System.out.println("5%2 = " + 5%2);
	System.out.println("-5%2 = " + -5%2);
	System.out.println("5%-2 = " + 5%-2);
	System.out.println("-5%-2 = " + -5%-2);
	
	System.out.println("----------------------------------");
	int a = -3;
	System.out.println(-a);
	
	System.out.println("----------------------------------");
	int i = 2;
	i++;
	System.out.println("i = " + i);
	
	int j = 2;
	++j;
	System.out.println("j = " + j);
	
	System.out.println("----------------------------------");
	int m = 1;
	int n = ++m;//m先自增,然后把m的值取出来赋值给n
	System.out.println("m = " + m);//2
	System.out.println("n = " + n);//2
	
	System.out.println("----------------------------------");
	int p = 1;
	int q = p++;//(1)先取出p的值"1",先放到一个“操作数栈”,(2)然后p变量完成自增(3)把刚才放在“操作数栈”中的值赋值给q
	System.out.println("p = " + p);//2
	System.out.println("q = " + q);//1
	
	System.out.println("----------------------------------");
	int z = 1;
	z = z++;//(1)先取出z的值"1",先放到一个“操作数栈”,(2)然后z自增,变为2(3)把刚才放在“操作数栈”中的值赋值给z
	System.out.println("z = " + z);
	
	System.out.println("----------------------------------");
	int b = 1;
	int c = 2;
	/*
	第一个:b++
	(1)先取b的值“1”,先放到一个“操作数栈”,
	(2)紧接着b就自增了,b=2
	第二步:++b
	(1)先b自增,b=3
	(2)紧接着再取b的值“3”,先放到一个“操作数栈”,
	第三步:++b
	(1)先b自增,b=4
	(2)紧接着再取b的值“4”,先放到一个“操作数栈”,
	第四步:c++
	(1)先取c的值“2”,先放到一个“操作数栈”,
	(2)紧接着c自增,c=3
	第五步:算乘 ++b和c++的乘法部分
	4*2 = 8 然后在压回“操作数栈”,
	第六步:再算 b++ + ++b + 乘的结果
		1 + 3 + 8 = 12
	*/
	int d = b++ + ++b + ++b * c++;
	System.out.println("b = " + b);//4
	System.out.println("c = " + c);//3
	System.out.println("d = " + d);//12
}
```

运算符:

4、逻辑运算符
逻辑与:&
类似于:且
true & true 结果为true
true & false 结果为false
false & true 结果为false
false & false 结果为false
逻辑或:|
类似于:或
true | true 结果为true
true | false 结果为true
false | true 结果为true
false | false 结果为false
逻辑非:!
类似于:取反
!true 结果为false
!false 结果为true
逻辑异或:^
类似于:求不同
true ^ true 结果为false
true ^ false 结果为true
false ^ true 结果为true
false ^ false 结果为false
短路与:&&
结果:和&是一样的
运算规则:如果&&的左边已经是false,右边就不看了
true & true 结果为true
true & false 结果为false
false & ? 结果为false
false & ? 结果为false
短路或:||
结果:和|是一样的
运算规则:如果||左边已经是true,右边就不看了
true | ? 结果为true
true | ? 结果为true
false | true 结果为true
false | false 结果为false

	public static void main(String[] args){
		/*
		判断成绩是否在70和80之间
		数学:70<=score<=80
		Java中:
		*/
		int score = -78;
		
		/*
		Test11_Logic.java:14: 错误: 二元运算符 '<=' 的操作数类型错误
                if( 70<=score<=80){
                             ^
		  第一个类型:  boolean   70<=score的运算结果是true或false
		  第二个类型: int
		1 个错误
		*/
		//if( 70<=score<=80){
		//	System.out.println("良好");
		//}
		
		if(70<=score & score<=80){
			System.out.println("良好");
		}
		
		/*
		假设成绩合理范围[0,100]
		判断成绩是否小于0 或 大于100,输出成绩有误
		*/
		if(score<0 | score>100){
			System.out.println("成绩有误");
		}
		
		/*
		假设成绩合理范围[0,100]
		判断成绩是否在合理范围内
		*/
		if(score>=0 & score<=100){
			
		}
		//或下面这么写
		if(!(score<0 | score>100)){
			
		}
		
		System.out.println(true ^ true);
		System.out.println(true ^ false);
		System.out.println(false ^ true);
		System.out.println(false ^ false);
		
		/*
		短路与:&&
		短路或:||
		*/
		int i = 1;
		int j;
		/*
		第一步:i++
		(1)先取i的值“1”,放起来
		(2)在i自增,i=2
		第二步:算比较
		放起来的“1” == 1比较,成立
		&&左边是true,不会短路
		第三步:++i
		(1)先自增i=3
		(2)再取i的值“3”,放起来
		第四步:比较
		放起来的“3” == 2比较,结果是false,不成立
		第五步:
		左边的true && 右边的false运算,结果为false,总的if不成立,走else
		*/
		//if(i++ == 1 && ++i == 2){
		//	j = 1;
		//}else{
		//	j = 2;
		//}
		
		/*
		第一步:i++
		(1)先取i的值“1”,放起来
		(2)在i自增,i=2
		第二步:算比较
		放起来的“1” == 1比较,成立
		||左边是true,会发生短路,右边不看了(++i == 2)没运算
		
		第三步:
		true || ?,结果为true,总的if成立
		*/
		if(i++ == 1 || ++i == 2){
			j = 1;
		}else{
			j = 2;
		}
		System.out.println("i = " + i);
		System.out.println("j = " + j);
	}

运算符:(了解)

6、位运算符
效率很高,但是可读性不好
因为它是基于二进制补码直接运算的。

左移:<<
运算规则:<<几位,就乘以2的几次方
二进制补码左移n位,右边补0
右移:>>
运算规则:>>几位,就除以2的几次方
二进制补码右移n位,左边补0还是1,看最高位
无符号右移:>>>
运算规则:二进制补码右移n位,左边补0,对于负数来说,移完后,变为正数
按位与:&
1 & 1 结果1
1 & 0 结果0
0 & 1 结果0
0 & 0 结果0
按位或:|
1 | 1 结果1
1 | 0 结果1
0 | 1 结果1
0 | 0 结果0
按位异或:^
1 ^ 1 结果0
1 ^ 0 结果1
0 ^ 1 结果1
0 ^ 0 结果0
按位取反:~(一元运算符)
~1为0
~0为1

	public static void main(String[] args){
		/*
		4的二进制:0000 0100
		4<<3:0 0100000
		*/
		System.out.println(4 << 3);//等价于4乘以2的3次方,4*8=32
		
		/*
		32的二进制:0010 0000
		32>>4:0000 0010 
		*/
		System.out.println(32 >>4);//等价于32除以2的4次方,32/16 =2
		
		/*
		-32的二进制:
			原码:1010 0000
			反码:1101 1111
			补码:1110 0000
		-32>>4:1111 1110 
			补码:1111 1110 
			反码:1111 1101
			原码:1000 0010
		*/
		System.out.println(-32 >>4);
		
		System.out.println(32 >>> 4);//和>>一样,左边补0
		/*
		-32的二进制:
			原码:1000 0000 0000 0000 0000 0000 0010 0000
			反码:1111 1111 1111 1111 1111 1111 1101 1111
			补码:1111 1111 1111 1111 1111 1111 1110 0000
		-32>>>4:0000 1111 1111 1111 1111 1111 1111 1110
			最高位是0,是正数
		*/
		System.out.println(-32 >>> 4);
		
		/*
		32:0000 0000 0000 0000 0000 0000 0010 0000
		25:0000 0000 0000 0000 0000 0000 0001 1001
		32 & 25:0000 0000 0000 0000 0000 0000 0000 0000
		*/
		System.out.println(32 & 25);
		
		/*
		32:0000 0000 0000 0000 0000 0000 0010 0000
		25:0000 0000 0000 0000 0000 0000 0001 1001
		32 | 25:0000 0000 0000 0000 0000 0000 0011 1001
		*/
		System.out.println(32 | 25);
		
		/*
		32:0000 0000 0000 0000 0000 0000 0010 0000
		25:0000 0000 0000 0000 0000 0000 0001 1001
		32 | 25:0000 0000 0000 0000 0000 0000 0011 1001
		*/
		System.out.println(32 ^ 25);
		
		/*
		3:0000 0000 0000 0000 0000 0000 0000 0011
		~3:1111 1111 1111 1111 1111 1111 1111 1100
		补码:1111 1111 1111 1111 1111 1111 1111 1100
		反码:1111 1111 1111 1111 1111 1111 1111 1011
		原码:1000 0000 0000 0000 0000 0000 0000 0100 -4
		*/
		System.out.println(~3);
	}

交换两个变量值的三种方法

	public static void main(String[] args){
		int x = 1;
		int y = 2;
		
		/*
		通用的方案:适用于任意的数据类型
				借助于第三个通样类型的临时变量
		*/
		int temp = x;//x变量中值就赋值给了temp  temp = 1
		x = y;//再把y中的值放到x中,x = 2
		y = temp;//再把temp中的值赋值给y  y=1
		System.out.println("x = " + x);
		System.out.println("y = " + y);
		
		x = 1;
		y = 2;
		/*
		方案二:只适用于int等整数类型
		*/
		x = x ^ y;
		y = x ^ y;//(新的x) ^ 原来的y = (原来的x ^ 原来的y) ^ 原来的y = 原来的x  (求不同)
		x = x ^ y;//(新的x) ^ 新的y = (原来的x ^ 原来的y) ^ 原来的x = 原来的y
		System.out.println("x = " + x);
		System.out.println("y = " + y);
		
		x = 1;
		y = 2;
		/*
		方案三:只适用于int等整数类型
			有风险,可能会溢出
		*/
		x = x + y;//有风险,可能会溢出
		y = x - y;//(新的x) - 原来的y = (原来的x + 原来的y)- 原来的y  = 原来的x
		x = x - y;//(新的x) - 新的y = (原来的x + 原来的y) - 原来的x = 原来的y
		System.out.println("x = " + x);
		System.out.println("y = " + y);
		
		/*
		以下不推荐
		*/
		x = 1;
		y = 2;
		x = x * y;//风险更大
		y = x / y;
		x = x / y;
	}

猜你喜欢

转载自blog.csdn.net/qq_40473204/article/details/107470307