Java數據類型(上)

一、java數據類型圖如下


二、java基本數據類型講解以及取值範圍

(一)整數類型

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類型的數據也存在同樣的問題,所以在浮點數表示中會產生些許的誤差,在單精度轉換爲雙精度的時候,也會存在誤差的問題,如下面的代碼,輸出結果就不一樣:

  1. float f = 2.2f;  
  2. double d = (double) f;  
  3. System.out.println(f);  
  4. System.out.println(d);  

對於能夠用二進制表示的十進制數據,如2.25,這個誤差就會不存在,所以會出現上面比較奇怪的輸出結果。

經過測試:float相乘計算和double相乘計算都不準確。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章