|
2-5 專題研討
內容:
2-5-1 範例研討:記錄最近 30 天收盤價
(A)程式功能:Ex2_6.java
請設計一套程式,除了可以隨時顯示最近 30 天的收盤價之外,也可以輸入每天的收盤價如何。注意,每天輸入收盤價之後,整個陣列會隨著移動,它會拋棄 30 天前收盤價,並擠入最近的收盤價(如圖 2-6),我們希望操作環境如下:
==
歡迎光臨
股票走勢分析系統
==
(1)
列印
30
日歷史收盤價
(2)
登錄當日收盤價
(3)
離開系統
請輸入工作選項
=>1
==
列印最近
30
日股價==
78.00
72.00 61.00 56.00 87.00
66.00
74.00 88.00 76.00 58.00
65.00
57.00 90.00 78.00 67.00
89.00
56.00 77.00 56.00 87.00
67.00
80.00 77.00 86.00 67.00
75.00
86.00 98.00 88.00 78.00
==
歡迎光臨
股票走勢分析系統
==
(1)
列印
30
日歷史收盤價
(2)
登錄當日收盤價
(3)
離開系統
請輸入工作選項
=>2
請登錄當日收盤股價
=>90
==
歡迎光臨
股票走勢分析系統
==
(1)
列印
30
日歷史收盤價
(2)
登錄當日收盤價
(3)
離開系統
請輸入工作選項
=>1
==
列印最近
30
日股價==
90.00
78.00 72.00 61.00 56.00
87.00
66.00 74.00 88.00 76.00
58.00
65.00 57.00 90.00 78.00
67.00
89.00 56.00 77.00 56.00
87.00
67.00 80.00 77.00 86.00
67.00
75.00 86.00 98.00 88.00
==
歡迎光臨
股票走勢分析系統
==
(1)
列印
30
日歷史收盤價
(2)
登錄當日收盤價
(3)
離開系統
請輸入工作選項
=> |
(B) 程式設計技巧
如想隨時得到某股票的歷史平均收盤價,必須紀錄該股票每日收盤價格;一日接一日的交替變化,需要紀錄的資料也可能無限延伸。當然不可能無限紀錄該股票的收盤價,再說太久之前的資料也可能沒有任何意思。但歷史資料記錄太少的話,也可能影響評估股價的正確性。本範例需要 30 日之前股票的收盤價,可利用由一維陣列製作的『佇列器』(Queue)來紀錄。圖 7-1 利用一只 30 個元素的一維陣列,儲存台積電近 30 日收盤價(假設數值);stock[0] 為前一日、stock[1] 為前二日、依此類推,stock[29] 記錄前第 30 日股價。當欲新登錄資料,則所有陣列元素往前移一個位置,原 stock[29] 資料拋棄,新資料填入 stock[0]。
圖 2-6 紀錄過去 30 日收盤價
假設某位分析師利用陣列 stock[] = {78, 72, 61, 56, 87, 66, 74, 88, 76, 58, 65, 57, 90, 78, 67, 89, 56, 77, 56, 87, 67, 80, 77, 86, 67, 75, 86, 98, 88, 78}; 儲存台積電最近 30 個交易日的收盤價,其中 stock[0] 為昨日股價,又 stock[29] 是之前第 30 日的收盤價。
(C) 程式範例
圖 2-7 Ex2_6 程式架構
程式範例如下:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 |
import
java.util.*;
public
class Ex2_6{
static
double stock[]={78, 72, 61, 56, 87,
66, 74, 88, 76, 58,
65, 57, 90, 78, 67,
89, 56, 77, 56, 87,
67, 80, 77, 86, 67,
75, 86, 98, 88, 78};
public
static void main(String args[]) {
Scanner keyin = new Scanner(System.in);
double cost;
int
select;
disp_menu();
select
= keyin.nextInt();
while(select != 3) {
switch(select) {
case 1:
disp_stock();
break;
case 2:
System.out.printf("請登錄當日收盤股價
=>");
cost = keyin.nextDouble();
for (int i=(30-1); i>=1; i--)
stock[i] = stock[i-1];
stock[0] = cost;
break;
default:
System.out.printf("輸入錯誤
!!
請重新輸入\n");
}
disp_menu();
select = keyin.nextInt();
}
}
static
void disp_menu() {
System.out.printf("==
歡迎光臨
股票走勢分析系統
==\n");
System.out.printf("(1)
列印
30
日歷史收盤價\n");
System.out.printf("(2)
登錄當日收盤價\n");
System.out.printf("(3)
離開系統\n");
System.out.printf("\t
請輸入工作選項
=>");
}
static
void disp_stock() { /*
列印
30
日內股價
*/
System.out.printf("\n==
列印最近
30
日股價==\n");
for(int
i=0; i<stock.length; i++) {
System.out.printf("%.2f ", stock[i]);
if((i+1) % 5 == 0)
System.out.printf("\n"); //列印五筆,
換行
}
System.out.printf("\n"); //
列印完畢,
換行
}
} |
2-5-2 自我挑戰:股票走勢分析系統
(A)程式功能:PM2_3.java
當股票分析師目標設定哪一股票(如台積電)後,大多會紀錄該股票過去收盤價,再利用資料分析最近該股的走勢,如果今天收盤價高於 1 5、30 日平均價,則稱為『多頭』走勢;如果高於 15 日但低於 30 日平均線,稱之為『盤整轉向多頭』;低於 15 日又高於 30 日,則稱為『盤整轉向空頭』;如果低於兩者,則為『空頭』走向。假設某位分析師利用陣列 stock[] = {78, 72, 61, 56, 87, 66, 74, 88, 76, 58, 65, 57, 90, 78, 67, 89, 56, 77, 56, 87, 67, 80, 77, 86, 67, 75, 86, 98, 88, 78}; 儲存台積電最近 30 個交易日的收盤價,其中 stock[0] 為昨日股價,又 stock[29] 是之前第 30 日的收盤價。請製作一股票走勢分析系統,且允許分析師增加當天收盤價、列印歷史收盤價、股票走勢如何;期望操作介面如下:
(a) 期望操作介面有 4 個功能選項
D:\Java2_book\chap2>java PM2_4
==
歡迎光臨
股票走勢分析系統 ==
(1)
列印 30
日歷史收盤價
(2)
登錄當日收盤價
(3)
分析目前股票走勢
(4)
離開系統
請輸入工作選項 => |
(b) 選擇列印 30 日歷史收盤價(選擇 1)操作如下:
請輸入工作選項 =>1
==
列印最近 30
日股價==
78.00 72.00 61.00 56.00 87.00
66.00 74.00 88.00 76.00 58.00
65.00 57.00 90.00 78.00 67.00
89.00 56.00 77.00 56.00 87.00
67.00 80.00 77.00 86.00 67.00
|
(C) 選擇登錄當日收盤價(選擇 2)操作如下:
請輸入工作選項 =>2
請登錄當日收盤股價 =>90 |
(D) 選擇分析目前股價走勢(選擇 3)操作如下:(空頭走勢)
請輸入工作選項 =>3
請輸入目前股價 =>50
15
日平均= 73.07, 30
日= 75.07
目前是空頭走勢
|
(E) 選擇分析目前股價走勢(選擇 3)操作如下:(多頭走勢)
請輸入工作選項 =>3
請輸入目前股價 =>98
15
日平均= 73.07, 30
日= 75.07
目前是多頭走勢
|
(F) 選擇分析目前股價走勢(選擇 3)操作如下:(盤整走勢)
請輸入工作選項 =>3
請輸入目前股價 =>75
15
日平均= 73.07, 30
日= 75.07
目前是盤整轉向多頭走勢
|
(B)製作技巧研討:
如何記錄過去 30 天交易日的收盤價,如圖 2-# 與範例 Ex2_6 分別表示製作方法。另外,計算 15 日平均價,則計算 stock[0] 到 stock[14] 的平均值;30 日平均價是 stock[0] ~ stock[29] 平均值,如此就可判斷該股票的走勢如何。如果目前價格來分析:
(1) 大於 15、30 日平均價,則為『多頭』走勢;
(2) 如低於 15、30 日兩者的平均價,則為『空頭』走勢;
(3) 如高於 15 日且低於 30 日是『盤整轉向多頭』;
(4) 其他(低於 15 日但高於 30)是『盤整轉向空頭』。
另一個重點,列印所有資料時,為了所輸出的報表較漂亮,每列印五筆資料後,就需換行。我們就依照該系統所應有的功能,將它分別寫成四個方法,其中 main() 為主程式、disp_menu() 功能是顯示功能選單、cal_ave(k) 為計算股票平均價使用,k 為計算最近天數 (15 或 30 日)、disp_stack() 為顯示所有股價的程式,整個類別架構如下圖所示。
虛擬碼提示如下:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 |
導入輸入套件(import
java.util.*;);
主類別範圍
{
宣告靜態陣列並設定初值(static
double stock[]={…..};
主程式範圍
{
宣告相關物件與變數;
顯示功能選項(disp_menu());
讀取功能選項(select
= keyin.nextInt());
while
(select !=4) {
switch(select) {
case 1:顯示
30
日收盤價(disp_stock());
case 2:讀取當日收盤價(cost);
移位陣列(for
(int I= 29 ~ 1) stock[I] = stock[I-1];);
當日填入(stock[0]
= cost;);
case 3:讀取目前股價(cost);
計算
15
日平均價(ave_15
= cal_ave(15));
計算
30
日平均價(ave_30
= cal_ave(30));
顯示平均價;
if
((cost>ave_15) && (cost>ave_30))
顯示多頭走勢;
else if
((cost <ave_15) && (cost <ave_30)
顯示空頭走勢;
else if
((cost >ave_15) && (cost <ave_30))
顯示盤整轉向多頭走勢;
if
((cost>ave_15) && (cost>ave_30))
顯示盤整轉向空頭走勢;
} //
switch/case
結束
顯示功能選項(disp_menu());
讀取功能選項(select
= keyin.nextInt());
} // while
結束
} //
主方法結束
顯示選單方法範圍(static
void disp_menu()){…..}
計算
k
日平均價範圍(static
double cal_ave(int k)){
double sum=0;
for(int I=0; I<k; I++)
sum = sum + stock[I];
return sum/k;
} // cal_ave()
結束
列印
30
日內所有股價範圍(static
void disp_stock()){
for(int i=0; i<stock.length; i++) {
System.out.printf(“%.2f “, stock[i]);
if(( i+1) % 5 == 0)
System.out.printf(“\n”); //列印五筆,
換行
}
System.out.printf(“\n”); //
列印完畢,
換行
} //
disp_stock
結束
} //
主類別結束 |
2-5-3 自我挑戰:印製國字收據
(A) 程式功能:PM2_4.java
請製作『真自在遊民收容所』的捐款收據,功能是系統允許輸入捐款人姓名與金額,之後印出收據但捐款數字需由國字印出,期望操作介面如下:
G:\Examples\chap4>java
PM2_4
請輸入大德先生/小姐姓名
= >tsnien
請輸入捐款金額
=>345678
列印收據如下:
****
真自在遊民收容所
捐款收據
****
感謝
tsnien
先生/小姐大德贊助
捐款
345678
元整
總計
= 零
仟
零
佰
參
拾
肆
萬
伍
仟
陸
佰
柒
拾
捌
元整
****
四海之內皆兄弟
順祝
平安快樂
**** |
(B)製作技巧提示:
本範例較困難的地方是數字轉換國字後,如何寫入適當的位置。我們設定一個範圍,比較容易設計列印格式,因此假設捐款最高為 9 千萬餘元(99999999,超過則另開收據);圖 7-2 為本範例列印格式(大多如此)。另外,我們可以利用整數相除得到某一位數(…百位、十位、個位),再利用餘數運算,得到取出某一位數後的剩餘值;另選一個陣列(int num[])存放每一位數的數字。讀取輸入捐款金額後(value),除以 1 千萬(10000000)得到千萬位的數字,再利用相同的數經過餘數運算,則扣除千萬位數,得到百萬以下的數值,依此類推則可得到相對位數的數字,並依序存入 num[] 陣列內。同時,選用 chinese[] 陣列存放每種數字的相對應國字,chinese[0] 存『零』(0)、chinese[1] 存『壹』(1)...等依此類推。
圖 2-8 國字列印格式
吾人再選用 doll[] 陣列存放列印次序的相對位數文字;則利用 chinese[num[i]]與 doll[i] 陣列交互列印,其中 i 為列印位數的指標;如此即可得到國字列印,虛擬碼提示如下:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19 |
宣告國字數字陣列(String
chinese[] = {"零",
"壹",
"貳",
"參",
.., "玖"});
宣告列印格式陣列(String
doll[] = {"仟",
"佰",
"拾",”萬”,
“仟”,
“佰”,
“拾”,
"元"};
宣告位數數字陣列(int[]
num = new int[9]);
宣告最高數字變數(千萬,base=10000000);
讀取捐款姓名(name);
讀取捐款額(value);
備份捐款額(value1
= value);
取出各個位數的數字:(最高
8
位數)
for (int i=0; i<8; i++) { //i=0,
仟萬;
i=1,
佰萬;
i=2,
拾萬;
…
num[i] = value / base;
value = value % base;
base = base /10;
}
列印捐款人姓名及金額(name,
value1);
列印捐款的國字:(最高
8
位數)
System.out.printf("\n總計
=");
for(int i=0; i<8; i++)
System.out.printf(" %s %s", chinese[num[i]], doll[i]);
System.out.printf("整
\n"); |
2-5-4 自我挑戰:統計滿意度平均值
(A) 程式功能:PM2_5.java
歡樂歌唱比賽邀請了 10 位老師當評審員,每位老師可給予 0~10 分,但記分方法是捨棄最高與最低分數後,再計算其餘 8 位老師的平均分數。期望操作介面,如下:
D:\Java2_book\chap2>javac PM2_5.java
D:\Java2_book\chap2>java PM2_5
請輸入第
1
位評審分數(0
~ 10)=>5
請輸入第
2
位評審分數(0
~ 10)=>1
請輸入第
3
位評審分數(0
~ 10)=>6
請輸入第
4
位評審分數(0
~ 10)=>7
請輸入第
5
位評審分數(0
~ 10)=>9
請輸入第
6
位評審分數(0
~ 10)=>9
請輸入第
7
位評審分數(0
~ 10)=>8
請輸入第
8
位評審分數(0
~ 10)=>7
請輸入第
9
位評審分數(0
~ 10)=>6
請輸入第
10
位評審分數(0
~ 10)=>7
有效評分:
5 6 6 7 7 7 8 9
平均分數為:
6.88 |
(B) 程式製作技巧
首先產生 10 個元素陣列 a[0]~a[9],分別讀入每位老師的評分後,再利用泡沫排序法,將 a[] 陣列由小到大排序,並捨棄 a[0] 與 a[9]後,再計算分均分數。
(C) 程式提示
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16 |
//PM2_5.java
….
import
java.util.Scanner;
public
class PM2_5{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int[] a = new int[10];
…..
while (count < 10) {
System.out.printf("請輸入第
%d
位評審分數(0
~ 10)=>", count+1);
a[count] = in.nextInt();
count++;
}
……..
}
} |
|
翻轉工作室:粘添壽
Java 程式設計(二) 含物件導向
翻轉電子書系列:
|