1 基本輸出入 與四則運算 本章大綱 5.1 本章的教學目標 5.2 Java 語言的運算子 5.3 算術與字串連接運算子 5.4 位元運算子 5.5 資料型態的轉換
5.1 本章的教學目標 程式語言有許多的算術運算所組成, 本章將介紹 Java 程式語言中基本輸出入運算子的功能與使用方式, 運算子包括 : 指定運算子 算數與字串連接運算子 位元運算子 資料型態的轉換運算子的功能與相關應用, 讓各位同學了解不同運算子的使用時機與應用方法 5.2 Java 語言的運算子 運算式 (expressions ) 是由一序列的 運算子 (operators ) 和 運算元 (operands) 組成, 可以在程式中執行所需的運算任務, 如圖 5.1 所示 : 圖 5.1 變數的觀念圖 由圖 5.1 可以得知 : 運算元表示被計算的內容, 而運算子則表是運算元之間的動作 a + b * 1 變數 a b 和常數值 1 是運算元, + * 為運算子 2
a = b + 1 變數 a b 和常數值 1 是運算元, + = 為運算子 當同一運算式擁有一個以上的運算子時, 運算式的執行結果會因運算子的執行順序而不 同, 必須特別注意一下 為了保證運算式得到相同的運算結果, 當運算式擁有多個運算子時, 運算子的執行順序是由優先順序和結合來決定 當在同一個運算式使用多個運算子時, 為了讓運算式能夠得到相同的運算結果, 運算式是以運算子預設的優先順序進行運算, 也就是我們所熟知的 先乘除後加減 口訣 a + b * 2 先計算 b*2 後才和 a 相加 在運算式中可以使用括號來推翻預設的運算子優先順序, 例如 : 改變上述運算式的運算順 序, 先執行加法運算後, 才是乘法 (a + b) * 2 先計算 a+b 後才和 2 相乘 單運算元運算式 單運算元運算式 (unary expressions) 只包含一個運算元和 單運算元運算子 ( unary operator) -15 +10 x++ --y 3
在 Java 語言的! - + ++ -- 和 ~ 是單運算元運算子, 這些運算子都擁有相同優先順 序, 所以是使用右左結合來進行運算式的計算 二元運算式 二元運算式 (binary expressions) 包含兩個運算元, 使用一個二元運算子來分隔運算元 a + b * 1 c + d + e 三元運算式 三元運算式 (ternary expressions) 包含 3 個運算元, 在 Java 語言只有一種三元運算子?: hour = (hour >= 12)? hour-12 : hour; 上述三元運算子擁有 (hour >= 12 hour-12 和 hour 共 3 個運算元 因為運算子擁有相同優 先順序, 所以是使用右左結合進行運算式的計算 Java 語言的運算子如表 5.1 所示 : 表 5.1 Java 語言的運算子 運算子 說明 () []. x++ y-- 括號 陣列元件 物件存取, 遞增和遞減是位在運算元之後! - ++x --y 條件運算子 NOT 算數運算子負號 遞增和遞減是位在運算元之 前 * / % 算術運算子的乘 除法和餘數 + - 算術運算子加和減法 << >> >>> 位元運算子左移 右移和無符號右移 4
> >= < <= instanceof 關係運算子大於 大於等於 小於和小於等於 ==!= 關係運算子等於和不等於 & ^ 位元運算子 AND 位元運算子 XOR 位元運算子 OR && 條件運算子 AND 條件運算子 OR?: 條件控制運算子 = op= 指定運算子 public class Ch4_1 { public static void main(string[] args) {int age, offset = 3; age = 18; age = age + 1; System.out.println("age = " + age); age += offset; System.out.println("age = " + age); 5.3 算術與字串連接運算子 Java 語言的 算術運算子 ( arithmetic operators ) 可以建立數學的算術運算式 (arithmetic expressions) Java 語言算術運算子和運算式, 其說明如表 5.2 所示 : 5
表 5.2 Java 語言算術運算子 運算子 說明 運算式 - 負號 -6 + 正號 +6 * 乘法 3 * 4 = 12 / 除法 7.0 / 2.0 = 3.5 7 / 2 = 3 % 餘數 7 % 2 = 1 + 加法 5 + 3 = 8 - 減法 5 3 = 2 後 算術運算子的 + 和 - 正負號是單運算元運算子, 只需 1 個運算元, 位在運算子之 +5 /* 數值正整數 5 */ -x /* 負變數 x 的值 */ 上述程式碼使用 + - 正負號表示數值是正數或負數, 單運算元運算子是使用右左結合 (right-to-left associativity) 執行運算 加法運算子 加法運算子 + 是將運算子前後的 2 個運算元相加 a = 6 + 7; /* 計算 6+7 的和後, 指定給變數 a */ b = c + 5; /* 計算變數 c 的值加 5 後, 指定給變數 b */ total = x + y + z; /* 將變數 x, y, z 的值相加後, 指定給變數 total */ 減法運算子 減法運算子 - 是將運算子前後的 2 個運算元相減, 即將之前的運算元減去之後的運算元 6
a = 8-2; /* 計算 8-2 的值後, 指定給變數 a */ b = c - 3; /* 計算變數 c 的值減 3 後, 指定給變數 b */ offset = x - y; /* 將變數 x 減變數 y 的值後, 指定給變數 offset */ 乘法運算子乘法運算子 * 是將運算子前後的 2 個運算元相乘 a = 5 * 2; /* 計算 5*2 的值後, 指定給變數 a */ b = c * 5; /* 計算變數 c 的值乘 5 後, 指定給變數 b */ result = d * e; /* 將變數 d, e 的值相乘後, 指定給變數 result */ 除法運算子 除法運算子 / 是將運算子前後的 2 個運算元相除, 也就是將之前的運算元除以之後的運算 元 a = 7 / 2; /* 計算 7/2 的值後, 指定給變數 a */ b = c / 3; /* 計算變數 c 的值除以 3 後, 指定給變數 b */ result = x / y; /* 將變數 x, y 的值相除後, 指定給變數 result */ 除法運算子 / 的運算元如果是 int 資料型態, 此時的除法運算是整數除法, 會將小數刪除, 所以 7 / 2 = 3, 不是 3.5 餘數運算子 % 運算子是整數除法的餘數,2 個運算元是整數, 可以將之前的運算元除以之後的運算 元來得到餘數 a = 9 % 2; /* 計算 9%2 的餘數值後, 指定給變數 a */ b = c % 7; /* 計算變數 c 除以 7 的餘數值後, 指定給變數 b */ result = y % z; /* 將變數 y, z 值相除取得的餘數後, 指定給變數 result */ 7
public class Ch4_2 { public static void main(string[] args) { System.out.println(" 負號運算 : -6 = " + (-6) ); System.out.println(" 正號運算 : +6 = " + (+6) ); System.out.println(" 乘法運算 : 3 * 4 = " + (3 * 4)); System.out.println(" 除法運算 : 7.0 / 2.0 = " + (7.0 / 2.0)); System.out.println(" 整數除法 : 7 / 2 = " + (7 / 2)); System.out.println(" 餘數運算 : 7 % 2 = " + (7 % 2)); System.out.println(" 加法運算 : 5 + 3 = " + (5 + 3)); System.out.println(" 減法運算 : 5-3 = " + (5-3)); 遞增和遞減運算子 Java 語言的遞增和遞減運算子 (increment and decrement operators) 是一種置於變數之前 或之後的運算式簡化寫法, 如表 5.3 所示 : 運算子說明運算式 表 5.3 Java 語言的遞增和遞減運算子 ++ 遞增運算 x++ ++xx -- 遞減運算 y-- --y 如果遞增和遞減運算子是使用在算術或指定運算式中, 運算子在運算元之前或之後就有 很大的不同, 如表 5.4 所示 : 8
表 5.4 前遞增 ( 減 ) 與後遞增 ( 減 ) 的差異表 運算子位置 說明 運算子在運算元之前 (++x --y) 先執行運算, 才取得運算元的值 運算子在運算元之後 (x++ y--) 先取得運算元值, 才執行運算 運算子是在運算元之後, 如下所示 : x = 10; y = x++; 上述程式碼變數 x 的初始值為 10,x++ 的運算子在後, 所以之後才會改變,y 值仍然為 10,x 為 11 運算元是在運算子之後, 如下所示 : x = 10; y = --x; 上述程式碼變數 x 的初始值為 10,--x 的運算子是在前, 所以 y 為 9,x 也是 9 public class Ch4_3 {public static void main(string[] args) {int x = 10, y = 10; x++; System.out.println(" 遞增運算 : x = 10 --> x++ = " + x); y--; 9
System.out.println(" 遞減運算 : y = 10 --> y-- = " + y); x = 10; y = x++; System.out.println("x = " + x); System.out.println("y = x++ = " + y); x = 10; y = --x; System.out.println("x = " + x); System.out.println("y = --x = " + y); 括號運算子 括號運算子的主要目的是為了推翻現有的優先順序 對於複雜的運算式來說, 我們可以使用 括號改變運算的優先順序 一般來說, 在運算式擁有超過 2 個運算子時, 我們才會使用括號來改變運算順序 a = b * c + 10; 上述運算式的運算順序是先計算 b * c 後, 再加上常數值 10, 因為乘法的優先順序大於加法 如果需要先計算 c + 10, 我們可以使用括號來改變優先順序, 如下所示 : a = b * (c + 10); 上述運算式的運算順序是先計算 c + 10 後, 再乘以 b a = (b * 2) + (c * (d + 10)); 上述運算式的運算順序是先計算最內層的 d + 10, 然後是上一層的 (b * 2) 和 (c * (d + 10)), 最後才計算相加的運算結果 public class Ch4_4 {public static void main(string[] args) 10
{int a, b, c, d; b = 10; c = 5; System.out.println("b = " + b + " c = " + c); a = b * c + 10; System.out.println("b * c + 10 = " + a); a = b * (c + 10); System.out.println("b * (c + 10) = " + a); d = 2; System.out.println("d = " + d); a = (b * 2) + (c * (d + 10)); System.out.println("(b * 2) + (c * (d + 10)) = " + a); 華氏 (fahrenheit) 和攝氏 (celsius) 溫度轉換攝氏轉華氏溫度的公式如下 : f = (9.0 * c) / 5.0 + 32.0; 華氏轉攝氏溫度的公式如下 : c = (5.0 / 9.0 ) * (f - 32); public class Ch4_5 {public static void main(string[] args) {double f, c; java.util.scanner sc =new java.util.scanner(system.in); System.out.print(" 請輸入攝氏溫度 => "); c = sc.nextdouble(); f = (9.0 * c) / 5.0 + 32.0; System.out.println(" 攝氏 " + c + "= 華氏 " + f + " 度 "); System.out.print(" 請輸入華氏溫度 => "); f = sc.nextdouble(); 11
c = (5.0 / 9.0) * (f - 32); System.out.println(" 華氏 " + f + "= 攝氏 " + c + " 度 "); 字串連接運算子 Java 的 + 運算子對於數值資料型態來說, 是加法, 可以計算兩個運算元的總和 如果運算元的其中之一或兩者都是字串時, + 運算子就是字串連接運算子, 可以連接多個字串變數 "ab" + "cd" "abcd" "Java 程式 "+" 設計 " "Java 程式設計 " public class Ch4_6 {public static void main(string[] args) {String str1 = "Java 是 "; String str2 = " 一種物件導向程式語言 "; System.out.println(" 字串連接 : " + (str1 + str2)); 5.4 位元運算子 位元運算子 (shift and bitwise operators) 是用來執行整數二進位值的位元運算, 提 供向左移或右移幾個位元的位移運算或 NOT AND XOR 和 OR 的位元運算, 如表 5.5 所 示 : 12
表 5.5 NOT AND XOR 和 OR 的位元運算表 運算子說明 ~ ~op1 位元的 NOT 運算, 運算元的位元值 1 時為 0,0 為 1 & op1 & op2 位元的 AND 運算,2 個運算元的位元值相同是 1 時為 1, 如果有一個為 0, 就是 0 op1 op2 位元的 OR 運算,2 個運算元的位元值只需有一個是 1, ^ op1 ^ op2 就是 1, 否則為 0 位元的 XOR 運算,2 個運算元的位元值只需任一個為 1, 結果為 1, 如果同為 0 或 1 時結果為 0 位元運算子的運算真值表如表 5.6 所示 : 表 5.6 位元運算子的運算真值表 a b NOT a NOT b a AND b a OR b a XOR b 1 1 0 0 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 0 0 0 其中 :a 和 b 代表二進位中的輸入位元 位元運算子 --AND 運算 & AND 運算 & 通常是用來將整數值的一些位元遮掉, 也就是說, 當使用 位元遮罩 (mask) 和數值進行 AND 運算後, 可以將不需要位元清成 0, 只取出所需位元 位元遮罩 0x0f 值可以取得 char 資料型態值中, 低階 4 位元的值, 如下所示 : 13
位元運算子 --OR 運算 OR 運算 可以將指定位元設為 1 OR 運算式 60 3, 如下所示 : 位元運算子 --XOR 運算 ^ XOR 運算 ^ 是當比較的位元值不同時, 即 0 和 1, 或 1 和 0 時, 將位元設為 1 XOR 運算式 60 ^ 120, 如下所示 : 位元運算子 左移 右移運算 ^ Java 語言提供向左移 ( left-shift) 右移(right-shift) 和無符號右移 ( unsigned rightshift) 幾種位移運算, 如表 5.7 所示 : 14
表 5.7 左移 右移和無符號右移運算表 運算子說明 << op1 << op2 >> op1 >> op2 左移運算,op1 往左位移 op2 位元, 然後在最右邊補上 0 右移運算,op1 往右位移 op2 位元, 最左邊補入 op1 最高位元 值, 正整數補 0, 負整數補 1 >>> op1 >>> op2 無符號右移運算,op1 往右位移 op2 位元, 然後在最左邊補 0 對於正整數來說, 左移運算每移 1 個位元, 相當於乘以 2; 右移運算每移 1 個位元, 相 當於是除以 2 原始十進位值 3 的左移運算, 在最右邊補 0, 如下所示 : 00000011 << 1 = 00000110 ( 6) 00000011 << 2 = 00001100 (12) 上述運算結果的括號就是十進位值 原始十進位值 120 的右移運算, 因為是正整數, 所以在最左邊補 0, 如下所示 : 01111000 >> 1 = 00111100 (60) 01111000 >> 2 = 00011110 (30) public class Ch4_5 {public static void main(string[] args) {int a = 0x3c; // 00111100 int b = 0x0f; // 00001111 int c = 0x03; // 00000011 int d = 0x78; // 01111000 int f = 0x03; // 00000011 int g = 120; // 01111000 15
int r; System.out.println("a/b 的值 = " + a + "/" + b); System.out.println("c/d 的值 = " + c + "/" + d); System.out.println("NOT 運算 : ~a = " + r); System.out.println("AND 運算 : a & b = " + r); System.out.println("OR 運算 : a c = " + r); System.out.println("XOR 運算 : a ^ d = " + r); System.out.println("f/g 的值 =" + f + "/" + g); System.out.println(" 左移運算 : f<<1 = " +(f<<1)); System.out.println(" 左移運算 : f<<2 = " +(f<<2)); System.out.println(" 右移運算 : g>>1 = " +(g>>1)); System.out.println(" 右移運算 : g>>2 = " +(g>>2)); 5.5 資料型態的轉換 資料型態轉換 (type conversions) 是因為運算式可能擁有多個不同資料型態的變數或文字值 例如 : 在運算式中同時擁有整數和浮點數的變數或文字值時, 就需要執行型態轉換 資料型態轉換是指轉換變數儲存的資料, 而不是變數本身的資料型態 因為不同型態佔用的位元組數不同, 在進行資料型態轉換時, 例如 :double 轉換成 float, 變數資料有可能損失資料或精確度 Java 指定敘述型態轉換 (assignment conversion) 可以分為兩種 : 寬基本型態轉換 (widening primitive conversions ) 和 窄基本型態轉換 (narrowing primitive conversions) 寬基本型態轉換將資料轉換成範圍比較大的資料型態, 運算式如果擁有不同型態的運算元, 就會將儲存的資料自動轉換成相同的資料型態 由於資料轉換成範圍比較大的資料型態不會損失精確度 ; 在指定敘述型態轉換的寬基本 16
型態轉換不需要特別語法, 也不會損失精確度 資料型別空間的關係 double > float > long > int > char > short > byte 態 上述型態的範圍是指如果 2 個運算元屬於不同型態, 就會自動轉換成範圍比較大的型 public class Ch4_6 {public static void main(string[] args) {int a = 123; float b = 15.5F; long c = 345678L; int r; long r1; float r2; double r3; // 寬基本型態轉換 System.out.print("a(i)=" + a + " b(f)=" + b); System.out.println(" c(l)=" + c); r = a + 134; System.out.println("r(i)=a(i)+134(i)=" + r); r1 = a + c; System.out.println("r1(l)=a(i)+c(l)=" + r1); r2 = a * b; System.out.println("r2(f)=a(i)*b(f)=" + r2); r3 = c * b; System.out.println("r3(d)=c(l)*b(f)=" + r3); 17
窄基本型態轉換與型態轉換運算子 窄基本型態轉換就是從精確度比較高的資料型態轉換成較低的資料型態 double 轉換成 float; long 轉換成 int; 變數儲存的資料將會損失一些精確度 指定敘述型態轉換的窄基本型態轉換通常並不會自動處理, 而是需要使用 Java 型態轉 換運算子 (cast operator) 在運算式中強迫轉換資料型態 強迫轉換資料型態語法 目的變數 =( 目的變數之型別 ) 來源變數 ; r1 = (float) a; r2 = (float) (a + b); int a,b; a=27; b=5; r = (float)a / (float)b; 上述程式碼將整數變數 a 和 b 都強迫轉換成浮點數 float, 此時 27/5 的結果是 5.4 public class Ch4_6_2 {public static void main(string[] args) {int a = 27; int b = 5; float r; // 寬基本型態轉換 18
System.out.println("a = " + a + " b = " + b); r = a / b; System.out.println("r = a / b = " + r); // 強迫型態轉換 r = (float)a / (float)b; System.out.println("r = (float)a/(float)b = "+r); ITSA 考題 問題描述 : 試撰寫一程式, 可由鍵盤輸入英哩, 程式的輸出為公里, 其轉換公式如下 : 1 英哩 = 1.6 公里 輸入說明 : 輸入欲轉換之英哩數 (int) 輸出說明 : 輸出公里 (double), 取到小數點以下第一位 執行 : 輸入 : 輸出 : 90 95 144.0 152.0 程式碼 : public class ch4_itsa_1 {public static void main(string[] args) {int mile; double km; java.util.scanner sc=new java.util.scanner(system.in); 19
System.out.print(" 入欲轉換之英哩數 (int):"); mile=sc.nextint(); km=(double)mile*1.6; System.out.println(" 輸出公里 (double)="+km); ITSA 考題 標準體重計算 問題描述 : 已知男生標準體重 =( 身高 -80 )*0.7; 女生標準體重 =( 身高 -70)*0.6; 試寫一個程式可 以計算男生女生的標準體重 輸入說明 : 每個測資檔案會有多組測資案例 輸入兩個數值, 依序代表為身高及性別 (1 代表男性 ;2 代表女性 ) 輸出說明 : 輸出標準體重, 浮點數取至第一位 : 輸入 : 輸出 : 172 1 165 2 64.4 57.0 程式碼 : public class ch4_itsa_2 {public static void main(string[] args) {int sex; double height,wei_std; java.util.scanner sc=new java.util.scanner(system.in); 20
System.out.print(" 請輸入身高 :"); height=sc.nextdouble(); System.out.print(" 請輸入性別 (1 代表男性 ;2 代表女性 ):"); sex=sc.nextint(); if(sex==1) wei_std=(height-80)*0.7; else wei_std=(height-70)*0.6; System.out.printf(" 標準體重為 : %.1f", wei_std); 21