这一块尤其是浮点数部分比较乱,《Java核心技术》写的太简略,参考的博客资料有些地方有冲突,但感觉主要理解其思想概念,具体的细节、精确度其实不用太在意。
最详细,看上去比较靠谱的是http://hujiantao224.iteye.com/blog/727155,不过太详细本渣都懒得看完了
当然最好的还是去看IEEE 754规范
Java是一种强类型语言,必须为每一个变量声明一个类型
一共8种基本类型:4种整型、2种浮点、一种布尔、一种字符(Char表示Unicode编码的字符单元)
Java为了解决平台移植问题,整型的范围和机器无关,每一种数据类型的取值范围固定
可以通过下面方式获取各个类型的字节数:
System.out.println("char:" + Character.SIZE);//char的长度是16
System.out.println("int:" + Integer.SIZE);//32
System.out.println("short:" + Short.SIZE);//16
System.out.println("long:" + Long.SIZE);//64
System.out.println("byte:" + Byte.SIZE);//8
System.out.println("float:" + Float.SIZE);//32
System.out.println("double:" + Double.SIZE);//64
转换关系:
在运算时,如果操作数类型不同会转换为同一类型,优先级为:double>float>long>int
对浮点数的舍入运算,得到的是最接近的整数
double y1=3.5,y2=3;
int x1=(int)Math.round(y1);//4
int x2=(int)Math.round(y2);//3
要强转成int,因为返回的是long
当强转使精度损失时,将高位字节截断,浮点数转整数去掉小数点后面的
int a=0b1_10000000;//不影响,128+256=384
byte b=(byte)0b1_10000000;//9位,多了一位,忽视第一位,补码,=-128
byte c=(byte)0b1_00000000;//忽视第一位,全0=0
(byte)300=44,只留300的后8位
整型
byte | 1字节 | -128 --- 127 |
short | 2字节 | -32768 --- 32767 |
int | 4字节 | 正负20亿 |
long | 8字节 |
byte a=(byte) 0b11111111;//输出-1
byte b=(byte) 0b10000000;//输出-128
byte c=(byte) 0b10000001;//输出-127
byte e= 0b1010000;//满8位时涉及最高位符号位,默认int,必须强转成byte、short,低于8位不需要转
short d=(short) 0b1000000000000000;//输出-32768
总之记住,补码表示的整数,全是1时取反+1,就是1.....1=-1啦
而100000则是最小的负数
长整型:后缀L(大小写都可以)
16进制:前缀0x(0X也可以)
8进制:前缀0
2进制:前缀0b
浮点数
float | 4字节(1符号位+8指数位+23尾数位) | 有效位数6~7位 |
double | 8字节(1符号位+11指数位+52尾数位) | 有效位数15位 |
看到一种说法:float放在内存中其实是当作double来处理的,它不会比double更节约内存资源,对应的double虚拟机会直接以double形式来进行处理,快速而且精度高,但是如果用float,不但不会节约内存资源,虚拟机为了校验float的精度,会花费更多的系统资源,例如cpu时钟,程序执行步骤等等。《Java核心技术》也认为float几乎很少用到,所以以后都用double吧
float后面要加F,没有后缀的浮点数都会默认为double
而double的指数范围:-1024~+1023
float的范围为-2^128 ~ +2^127(-3.40E+38 ~ +3.40E+38)这个正负2是因为,尾数部分最大为1.1111111.。。。?(第一位1默认确定)
double的范围为-2^1024 ~ +2^1023(-1.79E+308 ~ +1.79E+308)
float的指数范围:-128~+127(128还是127不太确定不过无所谓啦),8位都是数字位表示为0~255,然后减去一个偏差值127的方式得到-127~128总之范围基本一致。表示小数点可以左移127位(绝对值变小)到右移127位(绝对值变大)之间
尾数部分,规范规定,默认整数位是1,因此多了一位可以表示。23位却可以保存24位的尾数
博客中看到的例子:二进制的 1001.101(对应于十进制的 9.625)可以表达为 1.001101 × 2^3,所以实际保存在尾数域中的值为 00110100000000000000000,即去掉小数点左侧的 1,并 用 0 在右侧补齐。 (问题来了:第一位总是1,那浮点数的0咋表示)
所以可以表达的最大尾数为 2^24- 1 = 16,777,215 共8位,所以表示的十进制数字有效位小于等于8位
《Java核心技术》的意思可能是:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字,可能都是没考虑默认位,都少了1位有效数字
补充一点IEEE 754标准的情况,从百度百科里来的:
IEEE 754定义了4种浮点数值,32位,64位,43位,79位以上
二进制浮点数是以符号数值表示法格式储存,将最高效位元指定为符号位元(sign bit);
“指数部份”,即次高效的e位元,为浮点数中经指数偏差(exponent bias)处理过后的指数;
“小数部份”,即剩下的f位元,为有效位数(significand)减掉有效位数本身的最高效位元。
指数偏差(表示法中的指数为实际指数减掉某个值)为 ,其中的e为存储指数的比特的长度。减掉一个值因为指数必须是有号数才能表达很大或很小的数值,但是有号数通常的表示法——补码(two's complement),将会使比较变得困难。为了解决这个问题,指数在存储之前需要做偏差修正,将它的值调整到一个无符号数的范围内以便进行比较。此外,指数采用这种方法表示的优点还在于使得浮点数的正规形式和非正规形式之间有了一个平滑的转变
Java的科学计数法,指数的基数是10,e或者E都行
System.out.println(2.0E-3);//输出2*10^(-3)=0.002
16进制的科学计数法,标识是P,且指数的基数是2
System.out.println(0x1P2);//1*2^2=4
char
char b=\u0002;//错误,要加单引号
char b='\u002';//错误,unicode必须是4位数字,0也得加上去
char c='\u0002';//正确
String c="\u0041123";//字符串输出“A123”
char a='\u0041';
char c=65;
//两个都输出‘A’
\b | 退格 | \u0008 |
\t | 制表 | \u0009 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\"和\' | 引号 | \u0022、\u0027 |
\\ | 反斜杠 | \u005c |
boolean类型
if(aa=0){}//错误,不能将整型转为boolean