. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
Chapter 4
分支宣告與程式設計
Hung-Yuan Fan (范洪源)
Department of Mathematics, National Taiwan Normal University, Taiwan
Spring 2017
Outline
4.1 由上而下的設計方法 4.2 虛擬碼的使用 4.3 邏輯資料型態 4.4 分支
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
Section 4.1
由上而下的設計方法
由上而下的設計 (Top-Down Design)
是㇐種設計流程,首要之務是將㇐個大型工作計畫分成數個 較小而且較易處理的子計畫。
也是標準化程式設計流程的基礎,這些步驟包括
1 清楚地描述想要解決的問題
2 定義程式所需的輸入以及程式所產生的輸出
3 設計想要實施的演算法
4 把演算法轉換成 MATLAB 宣告式
5 測試完成的 MATLAB 程式
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
程式設計的流程圖
Section 4.2
虛擬碼的使用
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
虛擬碼 (Pseudocode)
以標準格式描述欲執行的演算法。
程式語言 (如 MATLAB、C、FORTRAN) 與英文的混合體。
虛擬碼的每㇐行用簡單又容易理解的英文,來敘述程式設計 人員的想法。
它的架構如同㇐般的程式語言,每㇐行代表㇐個特定的想 法,或是㇐小段程式碼,但是每㇐行的敘述都是英文。
為什麼要使用虛擬碼?
讓自己及其他人易於了解演算法的設計構想。
將虛擬碼轉換成 MATLAB 程式之前,協助組織自己的想法。
虛擬碼內容十分有彈性,而且容易修改。
虛擬碼對發展演算法是非常有用的!
虛擬碼的範例 (詳見範例 2.3, Sec. 2.12)
INPUT
temperature in degrees Fahrenheit. (華氏溫度)OUTPUT
temperature in kelvins. (絕對溫度或是克氏溫度)Step 1
Prompt user to enter temperature in degrees Fahrenheit.Step 2
Read temperature in degrees Fahrenheit (temp_f).Step 3
Computetemp_k
← (5/9) * (temp_f - 32) + 273.15.
Step 4
Write temperature in kelvins.. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
MATLAB 程式碼 (承上例)
% 提醒使用者輸入華氏溫度
temp_f = input('Enter the temperature (F): ');
% 將華氏溫度轉換為絕對溫度 ( kelvin) temp_k = (5/9)*(temp_f - 32) + 273.15;
% 輸出計算結果
fprintf('%6.2f (F) = %6.2f (K).
\n',temp_f, temp_k);
虛擬碼的範例 (㇐元二次方程式的勘根問題) To solve the root-finding problem
f(x) = ax 2
+ bx + c = 0 with a̸= 0.
INPUT
coefficients a, b, c.OUTPUT
approximate root x.Step 1
Compute the discriminant D = b2 − 4ac.
Step 2
Compute approximate root x to f(x) = 0 using D.Step 3
OUTPUT(x); STOP.. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
虛擬碼的範例 (高斯消去法)
Apply the Gaussian Elimination (GE) to solve a linear system
Mx = b,
where M
∈ R N ×N
is invertible and b∈ R N ×1
.INPUT
coefficient matrix M and the N-vector b.OUTPUT
approximate solution x∈ R N ×1
.Step 1
Set A(1)
= [M, b]∈ R N ×(N+1)
.Step 2
Use elementary row operations to computeA = A (1) → A (2) → · · · → A (N −1) → A (N) ,
where A(N)
is upper triangular.Step 3
Use the backward substitution to compute x.Section 4.3
邏輯資料型態
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
MATLAB 的資料型態
㇐般數值 (或浮點數) 資料型態
>> a = 3.2; b = single(3.2);
>> whos
a b
Name Size Bytes Class a 1
× 1 8
double b 1× 1 4
single. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
整數資料型態
n-bit 整數可分為有號(signed)與無號(unsigned)兩種:
整數資料型態的範例
>> uint8([12 300 -250]) ans =
12 255 0
>> int8(120) + int16(250) Error using +
Integers can only be combined with integers of the same class, or scalar doubles.
>> uint8(12) + uint8(64) >> uint8(12)^3
ans = ans =
76 255
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
字元資料型態
字元資料型態 (char) 是以成對的單引號括起來。
每㇐個字元佔了兩個位元組 (2 bytes)。
>> str = 'a string';
>> asc = double(str) asc =
97 32 115 116 114 105 110 103
>> char(asc) ans =
a string
>> char(65:90) ans =
ABCDEFGHIJKLMNOPQRSTUVWXYZ
邏輯資料型態
MATLAB 以 1 代表運算結果為真 (true),以 0 代表運算結 果為假 (false)。
邏輯資料型態的變數佔了㇐個位元組 (1 byte)。
>> a = true a =
1 % 不是數字 1 喔!
>> b = 0; c = logical(b) % 變數 b 是 double 資料型態 c =
0 % c 為邏輯變數,其內存值是假 (false)
>> logical([5 1 0 -2.4]) ans =
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
關係運算子 (relational operators)
由運算元間的關係產生邏輯(logical)值。
形式: a
1
op a2
範例
>> 2 > 4 >> 2 <= 4
ans = ans =
0 1
>> a = [1 0;-2 1]; >> a = [1 0;-2 1];
>> b = 0; >> b = [0 2;-2 -1];
>>
a > b
>>a >= b
ans = ans =
1 0 0 1
1 0 1 1
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
關於 == 與 ∼= 運算子
兩數值以相等運算子(==)運算:
相等:傳回 true 值(1)。
相異:傳回 false 值(0)。
兩數值以不相等運算子(
∼=)運算:
相等:傳回 false 值(0)。
相異:傳回 true 值(1)。
電腦計算過程會產生捨入誤差 (roundoff errors) 導致了相 等或不相等測試的失敗。
在某個誤差範圍內判斷兩者之間是否幾乎相等。
奇怪的運算結果
% 計算 0.01 連加 10 次的結果。
sum = 0;
for
ii = 1:10sum = sum +
0.01;
end
>> sum == 0.1 ans =
0 % 居然是假的 (false)!!
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
在數值計算上,如何判斷兩個浮點數相等?
>> a = 0; b = sin(pi) b =
1.2246e-16
>>
a == b
>>abs(a-b) < 1.0e-14
ans = ans =
0 (false) 1 (true)
邏輯運算子
作用在㇐或兩個邏輯運算元的運算子,並產生㇐個邏輯值。
總共有五種二元邏輯運算子:
AND(& 與 &&)
OR(| 與 ||)
非相容或互斥 OR(xor)
㇐元運算子:NOT(
∼)
㇐般形式: l
1
op l2
㇐元邏輯運算形式: op l
1
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
邏輯運算子
邏輯運算子的真值表
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
重要的 MATLAB 邏輯函式 (1/2)
這些函式可以與關係及邏輯運算子㇐起用來做為分支及迴圈運算 的控制。
重要的 MATLAB 邏輯函式 (2/2)
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
Section 4.4
分支 (Branches)
分支架構
分支(branches)是㇐種 MATLAB 宣告,允許我們選擇想 要執行的特定程式區塊(block),而跳過其他部分的程式 碼。
這些宣告可分成 if 架構、switch 架構,及 try/catch 架構。
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
if 與 if-else 選擇性敘述
if-else 敘述的流程圖
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
if 敘述的範例
i = input(' 請輸入㇐個數字: ');
% i 的內存值被改變!
if i > 0
% 判斷條件 x = 10; % 敘述主體end
if-else 敘述的範例
i = input(' 請輸入㇐個數字: ');
% i 的內存值被改變!
if i > 0
% 判斷條件 x = 10; % 敘述主體 1else
y = 5; % 敘述主體 2
end
上述範例的流程圖
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
if-else 敘述的範例
num = input(' 請輸入㇐個正整數: ');
if mod(num,2) == 0
fprintf('%g 是偶數
\n',num);
else
fprintf('%g 是奇數
\n',num);
end
if-elseif-else 選擇性敘述
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
if-elseif-else 敘述的範例
num = input(' 請輸入變數內容: ');
if
isinteger(num)disp(' 此變數是 n-bit 整數資料型態');
elseif
islogical(num)disp(' 此變數是邏輯資料型態');
elseif
isfloat(num)disp(' 此變數是浮點數資料型態');
else
disp(' 此變數是其他資料型態');
end
範例 4.2: ㇐元二次方程式 (1/6) 1. 宣告或敘述問題
撰寫 MATLAB 程式,求解㇐元二次方程式的零根 (zeros or rots),包含相異的實數根、重根,以及複數根。
2. 定義輸入與輸出 鍵入關鍵係數 a,b,c。
顯示零根解 x
1,2
= −b ±√
b2 − 4ac
2a 。 3. 設計演算法讀取輸入資料。
計算判別式 discriminant = b
2 − 4ac。
依據判別式是否大於零、等於零或小於零,各自輸出結果。
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
範例 4.2: ㇐元二次方程式 (2/6)
4. 把演算法轉成 MATLAB 宣告式 (檔名: calc_roots.m)
% Prompt the user for the coefficients
disp('This program solves for the roots of ');
disp('the equation A*X^2 + B*X + C = 0. ');
a = input('Enter the coefficient A: ');
b = input('Enter the coefficient B: ');
c = input('Enter the coefficient C: ');
% Calculate discriminant discriminant = b^2 - 4*a*c;
範例 4.2: ㇐元二次方程式 (3/6)
if
discriminant > 0 % two real rootsx1 = (-b + sqrt(discriminant)) / (2*a);
x2 = (-b - sqrt(discriminant)) / (2*a);
disp('This equation has two real roots:');
fprintf('x1 = %f
\n', x1);
fprintf('x2 = %f
\n', x2);
elseif
discriminant == 0 % one repeated root x1 = (-b) / (2*a);disp('This equation has one repeated root:');
fprintf('x1 = x2 = %f
\n', x1);
else
% omplex rootsre_part = (-b) / (2*a);
im_part = sqrt(abs(discriminant)) / (2*a);
disp('This equation has complex roots:');
fprintf('x1 = %f +i %f
\n',re_part,im_part);
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
範例 4.2: ㇐元二次方程式 (4/6) 5. 測試程式
>> calc_roots
This program solves for the roots of the equation A*X^2 + B*X + C = 0.
Enter the coefficient A: 1 Enter the coefficient B: 5 Enter the coefficient C: 6
This equation has two real roots:
x1 = -2.000000
x2 = -3.000000
範例 4.2: ㇐元二次方程式 (5/6)
>> calc_roots
This program solves for the roots of the equation A*X^2 + B*X + C = 0.
Enter the coefficient A: 1 Enter the coefficient B: 4 Enter the coefficient C: 4
This equation has one repeated root:
x1 = x2 = -2.000000
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
範例 4.2: ㇐元二次方程式 (6/6)
>> calc_roots
This program solves for the roots of the equation A*X^2 + B*X + C = 0.
Enter the coefficient A: 1 Enter the coefficient B: 2 Enter the coefficient C: 5
This equation has complex roots:
x1 = -1.000000 +i 2.000000
x2 = -1.000000 -i 2.000000
switch-case-otherwise 敘述
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
Remarks
switch 架構是另㇐種分支架構的形式。
switch 架構中的運算式或選擇值允許依據
1 整數值
2 字元字串
3 邏輯敘述
選擇執行某個特定程式區塊。
switch-case-otherwise 敘述的範例
value = input(' 請輸入介於 1 到 10 之間的正整數: ');
switch
valuecase
{1,3,5,7,9}disp(' 此數字是㇐個奇數。');
case
{2,4,6,8,10}disp(' 此數字是㇐個偶數。');
otherwise
disp(' 此數字不在預設範圍內喔!');
end
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . .
. .
. . . . .
switch-case-otherwise 敘述的範例
method = input('Enter the name of method: ','s');
switch
methodcase
{'linear','bilinear'}disp('Linear/Bilinear method.');
case
'cubic'disp('Cubic method.');
otherwise
disp('Unknown method!');