float和double在计算机中的存储
(1)一定是二进制存储 (2)最高位也是符号位 (3)float占4个字节,32位 double占8个字节,64位 (4)float来说,8位指数位 double来说,11位指数位 (5)float来说,23位尾数位 double来说,52位尾数位
结论(理解) (1)当小数的二进制尾数超过23或52之后,会截断,就会导致数据有差异,即不精确, 所以,我们把float和double称为浮点数。 (2)float和double类型能表示的数字范围比long类型等整数都要大 byte:1个字节 short:2个字节 int:4个字节 long:8个字节 float:4个字节 double:8个字节 (3)double类型比float类型精度相对要大一点 float类型,能表示到小数点7-8位,这里是十进制科学计数法的小数点右7-8位 double类型,能表示到小数点15-16位,这里是十进制科学计数法的小数点右7-8位
- 例如:8.25 第一步:转为二进制 8-->1000 0.25-->0.01
结合起来:1000.01
-
第二步:处理小数点 因为小数点很难表示,所以它干脆不表示
对刚刚的二进制进行处理,把它用“科学计数法”表示。 以十进制的数字为例,科学计数法演示一下: 256.87564 --> 科学计数法 2.5687564 * 10的2次方 0.000675 --> 科学计数法 6.75 * 10的-4次方
二进制的科学计数法: 1000.01 --> 科学计数法 1.00001 * n的3次方 1010100.0011 --> 科学计数法 1.0101000011 * n的6次方
发现:用科学计数法表示之后,小数点的左边永远是1(因为科学计数法的整数部分必须非0,而且是1位)
所以,这个整数部分的1就不存了,小数点也不存了
- 第三步:需要存储小数点右边的尾数 和 幂次方 对于float来说,8位用来存储幂次方,称为指数位 对于double来说,11位用来存储幂次方,称为指数位
对于float来说,32-1位符号位-8位指数位 = 23位的尾数位 对于double来说,64-1位符号位-11位指数位 = 52位的尾数位
8种基本数据类型: byte:1个字节 short:2个字节 int:4个字节 long:8个字节 float:4个字节 double:8个字节 char:2个字节 boolean:1个字节/1位 boolean在程序中只能表示为true或false,底层用1表示true,0表示false
由于小数是不能在计算机底层中准确表示的所以不能用==来判断两个浮点数类型相等。
double d1,d2; //... if(d1==d2){}//是错误的表达式,一定要避免
char类型底层怎么处理的?
(1)所有的字符都要转为二进制,即字符要用整数表示,这个整数就是字符的编码值 字符集:字符与整数编码对应的表格 最早的计算机只支持128个字符,有一个字符集称为ASCII码字符集。 欧洲等一些国家对ASCII码字符集进行扩展,扩展到256个。后面扩展的128个字符是不通用,在不同国家某个编码对应的字符是不同的。 亚洲等国家又扩展字符集,出现了很多很多不同的字符集。 例如: 中国,有GB2312(早期),GBK,Big5等字符集 现在默认用的是GBK。 后来,随着互联网的发展,一种更广的字符集应运而生,Unicode字符集,它支持全球所有的字符。
在Unicode字符集之前,字符集和编码方式是统一的, 例如:GBK既是字符集又是编码方式。 在Unicode字符集之后,要考虑很多因素,例如:一个二进制流到底要表示成几个字符等 Unicode字符集设定自己的几套解析的标准,称为编码方式。 有UTF-8,UTF-16等
二进制数据流: 11110101 10101100 10100010 10101111 01010100 ISO8859-1(ASCII的扩展版256位) 5个字符 GBK: 3个字符 UTF-8: 2个字符
(2)底层char类型是没有负数的,全部是正数 1个字节,能表示的编码值范围是:0-255(一共256) 2个字节,能表示的编码值范围是:0-65535 现在Java采用的就是Unicode字符集。
(3)所有的字符集都向下兼容ASCII码字符集 几个特殊的字符的编码大家需要掌握(必须记住) 'a'-->97, 'b'-->98 ... 'A'-->65, 'B'-->66 ... '0'-->48, '1'-->49 ... null-->0 TAB-->9
char类型在程序中如何表示?
(1)用单引号将一个字符引起来 例如:'a'
(2)可以直接用十进制编码值表示 十进制编码值的范围是:0-65535
(3)可以用十六进制表示编码值,一般是ASCII以外的才会用这种方式 例如:'尚'对应的编码值是23578(十进制),十六进制值是5C1A '\u5C1A' (4)对于一些特殊字符,还可以使用转义的方式表示 例如: 换行 '\n' TAB '\t' 从下一个制表位开始输出,每一个制表位默认是8位 退格:'\b' 回车:'\r' 结束本行 单引号:''' 双引号:'"' \本身:'\'
注意:
char类型变量在计算时会转换为int类型,
但char类型的常量计算时只要不超出char值的范围就还是char类型。
基本数据类型转换
(1)自动类型转换
- A:当存储范围小的变量/值等赋值给存储范围大的变量时,可以自动类型提升 byte-->short-->int-->long-->float-->double char--> B:当byte与byte,short与short,char与char,或者byte,short,char之间的运算,都会自动升级为int类型。 C:boolean不参与任何转换 D:当多种数据类型混合运算,按照它们当中最大的处理
(2)强制类型转换 格式:(最终要转为的数据类型)值/表达式
-
A:当我们把存储范围大的类型的变量/表达式等赋值给存储范围小的变量时,就需要强制类型转换 byte<--short<--int<--long<--float<--double char<-- 提示:这种情况强制类型转换有风险,可能会溢出或损失精度
-
B:当我们想要故意提示某个变量/值的数据类型,也可以使用强制类型转换 提示:这种情况强制类型转换没有风险
-
C:boolean不参与任何转换
String类型与基本数据类型的转换
(1)String类型与任意数据类型进行了“+”,结果都是字符串 (2)任何数据类型的值,只要加"",就是字符串 (3)String类型不能通过强制类型转换为基本数据类型
运算符
(1)分类
1.按照功能划分:
- 算术运算符
- 赋值运算符
- 比较运算符/关系运算符
- 逻辑运算符
- 条件运算符:? :
- 位运算符
2.按照需要的操作数的数量划分:
- 一元运算符: +a,a++
- 二元运算符: a+b, a>b, a = b
- 三元运算符: ? :
算术运算符
加:+ (1)如果是基本数据类型(boolean除外),+求和 (2)如果是有字符串参与,+表示拼接 减:- 乘:* 除:/ 如果是两个整数类型相除,结果只保留整数部分 模:% (1)求余数 (2)余数的正负号,与被除数一样 正:+ 负:- 自增:++,自增1 自减:--,自减1
以自增为例: (1)当自增表达式是独立的一个语句,++在前在后没有区别,结果都一样,都是自增变量+1 例如: i++; ++i;
(2)当自增表达式不是独立的语句,它是其他运算或者是语句的一部分,那么++在前在后不一样。 ++a:++在前,先自增(+1),再取自增变量的值,参与其他运算 a++:++在后,先取自增变量的值,然后自增变量自增(+1),再用取出来的值参与其他运算
赋值运算符
最最基本的赋值运算符是= 作用:把=右边的值/表达式结果赋值给=左边的变量,即修改左边变量的值
(1)=左边一定是一个变量 (2)=的优先级是最低的,一定是最后算
赋值运算符还有扩展的系列: +=,-=,*=,/=,%=....
(1)把=右边看成一个整体,然后用=左边的变量与右边的值/表达式的结果做+,-等运算。 (2)+=,-=,*=,/=,%=....算完的结果类型的范围如果超过左边的变量,会隐含强制类型转换, 所以结果可能是错误的(溢出或损失精度)
关系运算符/比较运算符
大于:> 小于:< 等于:== 大于等于:>= 小于等于:<= 不等于:!=
(1)关系运算符通常用在条件判断中 (2)关系运算符的表达式结果只有两种:true/false
逻辑运算符
逻辑与:两个条件同时成立 & 只有&符号的两边都是true,结果才为true true & true 结果是true true & false 结果是false false & true 结果是false false & false 结果是false 逻辑或:| 只要|符号的两边有一边是true,结果就为true true | true 结果是true true | false 结果是true false | true 结果是true false | false 结果是false 逻辑异或:^ 只有^符号的两边一边是false,一边是true,结果才为true true ^ true 结果是false true ^ false 结果是true false ^ true 结果是true false ^ false 结果是false 逻辑非:! !true 变为false !false 变为true 短路与:&& 只有&&符号的两边都是true,结果才为true true && true 结果是true true && false 结果是false false && ? 结果是false &&的效率比&高,因为当&&的左边为false时,右边就不看了,结果直接是false 短路或 只要||符号的两边有一边是true,结果就为true true || ? 结果是true false || true 结果是true false || false 结果是false ||的效率比|高,因为当||的左边是true时,右边就不看了,结果直接是true
(1)逻辑运算符是用来表示两个条件之间的关系 (2)逻辑运算符表达式的结果仍然是true和false (3)逻辑运算符表达式仍然作为条件使用
条件运算符,唯一的三元运算符
格式: 条件表达式 ? 结果表达式1 : 结果表达式2 运算: 当条件表达式成立时,取结果表达式1的结果,否则取结果表达式2
位运算符(效率最高的运算符)
按位与:& 只有对应的二进制位都是1,结果才为1 1 & 1 结果是1 1 & 0 结果是0 0 & 1 结果是0 0 & 0 结果是0 按位或:| 只要对应的二进制位有1,结果就为1 1 | 1 结果是1 1 | 0 结果是1 0 | 1 结果是1 0 | 0 结果是0 按位异或:^ 只有对应的二进制位一个是1一个是0,结果才为1 1 ^ 1 结果是0 1 ^ 0 结果是1 0 ^ 1 结果是1 0 ^ 0 结果是0 按位取反:~ ~1:0 ~0:1
左移:<< (1)整体二进制左移,右边补0, (2)快速口诀,左移几位相当于乘以2的几次方 (3)当左移的位数超过 当前数据类型的总位数,那么要减去总位数 例如:int类型总位数是32,左移35位的话,相当于左移3位
只有左移<<会发生循环的现象,比如说左移越界的1,会在最右边出现
右移:>> (1)整体二进制右移,如果原来最高位是0,左边补0,原来最高位是1,左边补1 (2)快速口诀,右移几位相当于除以2的几次方,向下取整 (3)当右移的位数超过 当前数据类型的总位数,那么要减去总位数 例如:int类型总位数是32,右移35位的话,相当于右移3位 无符号右移:>>> (1)整体二进制右移,左边补0,不看符号位
class Test12BitOperator{
public static void main(String[] args){
System.out.println(1 & 2);
/*
1:0000 0000 0000 0000 0000 0000 0000 0001
2:0000 0000 0000 0000 0000 0000 0000 0010
&:0000 0000 0000 0000 0000 0000 0000 0000
*/
System.out.println(3 & 5);
/*
3:0000 0000 0000 0000 0000 0000 0000 0011
5:0000 0000 0000 0000 0000 0000 0000 0101
&:0000 0000 0000 0000 0000 0000 0000 0001
*/
System.out.println(-3 & 5);
/*
-3:
原码:1000 0000 0000 0000 0000 0000 0000 0011
反码:1111 1111 1111 1111 1111 1111 1111 1100
补码:1111 1111 1111 1111 1111 1111 1111 1101
5: 0000 0000 0000 0000 0000 0000 0000 0101
&: 0000 0000 0000 0000 0000 0000 0000 0101
*/
System.out.println(1 | 2);
/*
1:0000 0000 0000 0000 0000 0000 0000 0001
2:0000 0000 0000 0000 0000 0000 0000 0010
|:0000 0000 0000 0000 0000 0000 0000 0011
*/
System.out.println(-3 | 5);
/*
-3:
原码:1000 0000 0000 0000 0000 0000 0000 0011
反码:1111 1111 1111 1111 1111 1111 1111 1100
补码:1111 1111 1111 1111 1111 1111 1111 1101
5: 0000 0000 0000 0000 0000 0000 0000 0101
|: 1111 1111 1111 1111 1111 1111 1111 1101(补码)
*/
System.out.println(1 ^ 2);
/*
1:0000 0000 0000 0000 0000 0000 0000 0001
2:0000 0000 0000 0000 0000 0000 0000 0010
^:0000 0000 0000 0000 0000 0000 0000 0011
*/
System.out.println(-3 ^ 5);
/*
-3:
原码:1000 0000 0000 0000 0000 0000 0000 0011
反码:1111 1111 1111 1111 1111 1111 1111 1100
补码:1111 1111 1111 1111 1111 1111 1111 1101
5: 0000 0000 0000 0000 0000 0000 0000 0101
^: 1111 1111 1111 1111 1111 1111 1111 1000(补码)
1111 1111 1111 1111 1111 1111 1111 0111(反码)
1000 0000 0000 0000 0000 0000 0000 1000(原码)-8
*/
System.out.println(~1);
/*
1: 0000 0000 0000 0000 0000 0000 0000 0001
~1:1111 1111 1111 1111 1111 1111 1111 1110(补码)
1111 1111 1111 1111 1111 1111 1111 1101(反码)
1000 0000 0000 0000 0000 0000 0000 0010(原码)-2
*/
System.out.println(1 << 5);
/*
1: 0000 0000 0000 0000 0000 0000 0000 0001
1<<5 0000 0000 0000 0000 0000 0000 0010 0000
*/
System.out.println(11 << 2); //44
/*
11: 0000 0000 0000 0000 0000 0000 0000 1011
11<<2: 0000 0000 0000 0000 0000 0000 0010 1100
*/
System.out.println(1 << 35);//8 等价于1<<(35-32) 本来应该消失的1,在右侧移动回来了
System.out.println(1 >> 5);
/*
1: 0000 0000 0000 0000 0000 0000 0000 0001
1>>5 0000 0000 0000 0000 0000 0000 0000 0000
*/
System.out.println(100 >> 5);//3 100/2的5次=100/32 只保留整数部分,向下取整
/*
100: 0000 0000 0000 0000 0000 0000 0110 0100
100>>5:0000 0000 0000 0000 0000 0000 0000 0011
*/
System.out.println(-1 >> 5);
/*
-1:原码:1000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111
-1>>5: 1111 1111 1111 1111 1111 1111 1111 1111(补码)
*/
System.out.println(-100 >> 35); //-100/2的3次= -100/8 -13 向下取整
/*
-100:
原码:1000 0000 0000 0000 0000 0000 0110 0100
反码:1111 1111 1111 1111 1111 1111 1001 1011
补码:1111 1111 1111 1111 1111 1111 1001 1100
-100>>35等价于-100>>3
1111111 1111 1111 1111 1111 1111 1001 1(补码)
1111111 1111 1111 1111 1111 1111 10010(反码)
1000000 0000 0000 0000 0000 0000 01101(原码)
*/
System.out.println(-1 >>> 5);
/*
-1:原码:1000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111
-1>>>5: 0000 01111 1111 1111 1111 1111 1111 111 (134217727)
*/
}
}
输出
(1)System.out.println(xxx); 输出xxx之后换行 (2)System.out.print(xxx); 输出xxx之后不换行 (3)System.out.printf("格式符号" , 变量列表); 了解,看看就完了,是兼容C语言的输出习惯,Java基本上不用格式化输出 小数:%f,如果要保留小数点后几个 %.几位f
仅了解即可,如有保留小数点后几位的需求,最好不要使用这种方法,开发过程中也不会在控制台进行输出
整数:%d 字符串:%s boolean:%b char:%c
class Test13Out{
public static void main(String[] args){
System.out.println("hello");
System.out.println("world");
System.out.println("-----");
System.out.print("atguigu");
System.out.print("java");
System.out.println("-----");
System.out.print("atguigu\n");
System.out.print("java");
System.out.println("-----");
double d = 13.45623;
System.out.printf("%.2f\n", d);
char c = 'a';
System.out.printf("%c" , c);
}
}