Java 基本資料型態你要知道的2件事

更新於 發佈於 閱讀時間約 7 分鐘

所謂的資料型態就是儲存資料的種類,比如Excel中可以針對文字、數字、日期不同種類的資料進行儲存跟運算,程式語言中也是如此,目的都是幫你把各種資料放到電腦記憶中進行加減乘除的運算,Java Primitive Type,我們稱為基本型態,一共有8種分別是整數有4種(byte short int long)、小數2種(float double)、文字以及布林值。

這裏我們提兩件重要的事

Overflow 資料溢位

Overflow中文翻譯成叫「資料溢位」,這名詞翻的很道地,就明白的跟你說資料多到滿出來了。

int overflow = 2000000000 + 2000000000;  <- 這裏是20(2後面90)加上20億,正常應該是40

System.out.println("overflow = " + overflow);

執行結果如下:

overflow = -294967296

結果是一個負值,這其實是因為加起來後其實是40億,但已經超過了int 21億的範圍,導致加相後的位元溢出至正負號位而發生的錯誤。這種錯誤很危險,因為在執行過程中並沒有任何錯誤訊息提示。

想像一下如果你有20億,你再存了20億去銀行,但櫃台跟你說:先生,你現在欠我們銀行2億多。

int的極限值可以利用以下程式,最大值大概是21億多

System.out.println(Integer.MAX_VALUE);//最大值:2147483647
System.out.println(Integer.MIN_VALUE);//最小值:-2147483648

那宣告成long應該就沒問題了吧

long overflow = 2000000000 + 2000000000;  
計算的結果依然是 -294967296

結果依然是負值,原因是Java運算中有一個規則

符號(+)兩邊相同型態的變數運算時(以這個例子來說就是上方的2個20億都是int,也就是 int+ int),則運算結果也會為同一型態(int),也因為最後計算的結果還是int,int又只能放入21億左右的值,放不下40億,所以計算的結果還是會發生overflow。

Java Language Spec 5.6.2 中有明確定義了在兩個不同型態的變數計算時的運算規則。

如果符號左右兩側的變數型態不同呢?有以下的規則

  • If either operand is of type double, the other is converted to double.
  • Otherwise, if either operand is of type float, the other is converted to float.
  • Otherwise, if either operand is of type long, the other is converted to long.
  • Otherwise, both operands are converted to type int.

簡單的來說,如果有一邊型態是double,則自動把另一邊轉成double,以下面的例子來說a是double, b 的型態是int,計算時會double + int ,會自動把另一邊轉成double,再進行運算,此時因為兩邊都是double,所以計算結果也會是double。

double a = 3.0;
int b = 10;
double c = a + b ;
// =double + int -> double + double -> 結果為double

以照上述官方的規則,由上往下判斷

  1. 如果兩邊沒有double,就看看有沒有float,有任何一邊變數為float就都轉成float
  2. 如果兩邊沒有double float,就看看有沒有long,計算的結果為long
  3. 兩邊找不到double float long,就都轉成int進行計算,所以計算的結會是int

在這個例子裏,計算時就只能使用long來處理,比如把第一個20億改成long的型態,就是加個L在最後面

long overflow = 2000000000L + 2000000000;  
= long + int
把另一邊轉成long= long + long -> long
計算的結果 4000000000就不會因為存到int中而導致overflow


浮點數的精度

浮點數包含了float 跟 double,其中float為單精度浮點數(精度6~7位) 4 bytes,double為雙精度浮點數(15~16位) 8 bytes。我們來看一下什麼是精度

float a= 123.4567890123456789f;
double b=123.4567890123456789;
System.out.println(a);//結果 123.45679
System.out.println(b);//結果 123.45678901234568
System.out.println(0.1+0.1+0.1); //0.30000000000000004
  1. 精度上,float最多只能記錄7位數字,所以System.out.println(a) 只能印出123.45679。(劃線的部分只有7位)
  2. double大概15-16位左右,System.out.println(b); 印出 123.45678901234568。(劃線的部分只有16位)
  3. 在計算上也會造成誤差,0.1+0.1+0.1,最後卻在小數點很後面的地方多了一個4出來
  4. float 跟double在使用上必須留意,因為有精度上的問題,加減乘除多了會造成精度損失被放大,在計算錢的方面某些情境下可能不適合,需要小數點精細計算可以使用java.math.BigDecimal替代進行較精確的計算。
  5. 精度雖然有誤差,但計算速度很快,在能接受誤差的情況下就很適合使用。比如我們的需求只是要記錄一公升汽油可以跑幾公里,有些誤差是無傷大雅的。


留言
avatar-img
留言分享你的想法!
avatar-img
漸進超負荷工程師
0會員
5內容數
介紹Java語法