Java資料類型(上)
一、java資料類型圖如下
二、java基礎資料型別 (Elementary Data Type)講解以及取值範圍
(一)整數類型
1、byte類型
byte在電腦中是佔8位的,而且byte是有符號整形,用二進位表示時候最高位為符號位0代表正數1代表負數。預設是0。
取值範圍:-128到127(-2的7次方到2的7次方減1)
擴充(取值範圍計算):
正數在電腦中是以原碼形式存在的,負數在電腦中是以其補碼形式存在的,就是負數的絕對值的原碼轉為二
進位再按位取反後加1。
我們來看-128絕對值128的二進位表示:1000 0000按位取反0111 1111加1後:1000 0000,也就是說-128在電腦
中的表示就是1000 0000了,再來看一下-129在電腦中的表示絕對值129的範圍已經超出了了byte的位
數。所以要注意這類問題。
2、short類型
short(短整型)一個short 16位,取值範圍為-32768~32767,在記憶體中佔用2個位元組(-2的15次方到2的15次方-1)預設是0
3、int類型
int(整型)一個int 32位,取值範圍為(-2147483648~2147483647),在記憶體中佔用4個位元組(-2的31次方到2的31次方-1)預設是0
4、long類型
long(長整型)一個long 64位,取值範圍為(-9223372036854774808~9223372036854774807),在記憶體中佔用8個位元組(-2的63
次方到2的63次方-1)預設是0L或0l推薦用大寫。
可以看到byte和short的取值範圍比較小,而long的取值範圍太大,佔用的空間多基本上int可以滿足我們的日常的計算了,而且
int也是使用的最多的整數型別了。在通常情況下,如果JAVA中出現了一個整數數字比如35,那麼這個數字就是int型的,但是如果要表
示long型的就一定要在資料後面加"L"。
byte深入測試(其他類型同理):
public static void main(String[] args) {
/**
* byte類型賦值問題: 負數需要在數實值型別前加“-”,如果不標明則說明是正數(-表示負數,+表示正數,+可省略)
* 數值(正數或負數)首位沒有0,則預設為十進位 數值(正數或負數)首位包含0(除0x為首位的情況),則表明為八進位(如:011)
* 數值(正數或負數)首位包含0x,則表明為十六進位(如:0x11或0X11)
* 將八進位、十進位、十六進位強制類型轉換成byte類型,會丟失精度,byte取值範圍為:-128到127
*/
// 八進位(十進位為9),該值輸出為9
byte byte_bajinzhi = 011;
// 八進位(十進位為-9),該值輸出為-9
byte byte_bajinzhi_fushu = -011;
// 八進位(十進位為585,超出byte取值範圍),該值輸出結果為,十進位為73(0111八進位)
byte byte_bajinzhi_zhuanhuan = (byte) 01111;
// 十進位,該值輸出結果不變為111
byte byte_shijinzhi = 111;
// 十進位,超過byte取值範圍,此值輸出結果為-127
// 注意:正數在電腦的儲存就是此正數的原碼;負數在電腦的儲存為負數的絕對值的原碼轉為二進位再按位取反後加1
// 計算過程:129在電腦儲存的,原碼為:127+2(10000001)(說明:127為01111111,加2後10000001,
// 10000001為電腦的儲存,可以看出此值為負數,將首位1去掉,轉換來列印到控制台,轉換方式:先減1,為0000000,然後按位取反得1111111(127),則最後輸出結果為-127)
byte byte_shijinzhi_zhuanhuan = (byte) 129;
// 十六進位(十進位為17),該值輸出為17
byte byte_shiliujinzhi = 0x11;
// 八進位(十進位為-17),該值輸出為-17
byte byte_shiliujinzhi_fushu = -0x11;
System.out.println("byte_bajinzhi:" + byte_bajinzhi);
System.out.println("byte_bajinzhi:" + byte_bajinzhi_fushu);
System.out
.println("byte_bajinzhi_zhuanhuan:" + byte_bajinzhi_zhuanhuan);
System.out.println("byte_shijinzhi:" + byte_shijinzhi);
System.out.println("byte_shijinzhi_zhuanhuan:"
+ byte_shijinzhi_zhuanhuan);
System.out.println("byte_shiliujinzhi:" + byte_shiliujinzhi);
System.out
.println("byte_shiliujinzhi_fushu:" + byte_shiliujinzhi_fushu);
}
測試結果如下:
byte_bajinzhi:9
byte_bajinzhi:-9
byte_bajinzhi_zhuanhuan:73
byte_shijinzhi:111
byte_shijinzhi_zhuanhuan:-127
byte_shiliujinzhi:17
byte_shiliujinzhi_fushu:-17
(二)浮點類型
1、float類型
記憶體結構如下:
1bit(符號位) 8bits(指數位) 23bits(尾數位)
2、double類型
記憶體結構如下:
1bit(符號位) 11bits(指數位) 52bits(尾數位)
於是,float的指數範圍為-128~+127,而double的指數範圍為-1024~+1023,並且指數位是按補碼的形式來劃分的。
其中負指數決定了浮點數所能表達的絕對值最小的非零數;而正指數決定了浮點數所能表達的絕對值最大的數,也即決定了浮點數的取值範圍。
float的範圍為-2^128 ~ +2^127,也即-3.40E+38 ~ +3.40E+38;double的範圍為-2^1024 ~ +2^1023,也即-1.79E+308 ~ +1.79E+308。
3、精度討論
float和double的精度是由尾數的位元來決定的。浮點數在記憶體中是按科學計數法來儲存的,其整數部分始終是一個隱含著的“1”,由於它是不變的,故不能對精度造成影響。
float:2^23 = 8388608,一共七位,由於最左為1的一位省略了,這意味著最多能表示8位元: 2*8388608 = 16777216 。有8位有效數字,但絕對能保證的為7位,也即float的
精度為7~8位有效數字;double:2^52 = 4503599627370496,一共16位,同理,double的精度為16~17位。
對於小數來說,更容易會因為精度而出錯誤。
測試:
測試代碼:
float f = 2.2f;
double d = (double) f;
System.out.println(d);
f = 2.25f;
d = (double) f;
System.out.println(d);
測試結果:
2.200000047683716
2.25
------------------------------------------------------------------------------------測試結果分析-----------------------------------------------------------------------------------------------------------------------------
首先我們看看2.25的單精確度儲存方式,轉化為2進位位便是10.01,整理為1.001*2 很簡單
於是我們可以寫出2.25的記憶體分布:
符號位為:0
指數為1,用補碼錶示 0000 0001,轉為移碼就是1000 0001。
尾數位為0010 0000 0000 0000 0000 000
而2.25的雙精確度表示為:0 100 0000 0001 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000,這樣2.25在進行強制轉換的時候,數值是不會變的,而我們再
看看2.2呢,2.2用科學計數法表示應該為:將十進位的小數轉換為二進位的小數的方法為將小數*2,取整數部分,所以0.282=0.4,所以二進位小數第一位為0.4的整數部分0,0.4×2
=0.8,第二位為0,0.8*2=1.6,第三位為1,0.6×2 = 1.2,第四位為1,0.2*2=0.4,第五位為0,這樣永遠也不可能乘到=1.0,得到的二進位是一個無限迴圈的排列 0011001100110011
0011... ,對於單精確度資料來說,尾數只能表示24bit的精度,所以2.2的float儲存為
但是這樣儲存方式,換算成十進位的值,卻不會是2.2的,因為十進位在轉換為二進位的時候可能會不準確,如2.2,而double類型的資料也存在同樣的問題,所以在浮點數表示中會產生些許的誤差,在單精確度轉換為雙精確度的時候,也會存在誤差的問題,如下面的代碼,輸出結果就不一樣:
- floatf=2.2f;
- doubled=(double)f;
- System.out.println(f);
- System.out.println(d); 對於能夠用二進位表示的十進位資料,如2.25,這個誤差就會不存在,所以會出現上面比較奇怪的輸出結果。