Transcript Chapter 9

第九章 程式控制流程
本章學習目標
• 認識關係運算子與邏輯運算子
• 學習選擇性敘述的用法
• 學習各種迴圈的用法
• 探討迴圈的效率問題
1
關係運算子
• 關係運算子(relational operators)可用來比較二數字之間
的大小。
>> 4<=12
ans =
1
>> 5>6
ans =
0
>> test=[1 3 4]<[2 2 1]
test =
1
0
0
>> whos test
Name
Size
test
1x3
Bytes Class
3
logical array
2
logical陣列之建立與應用
>> a=[1 0 1 1]
a =
1
0
>> logical(a)
ans =
1
0
1
1
1
>> a=[-1 0 2 3 1 5]
a =
-1
0
2
3
1
5
1
>> b=a<2
b =
1
1
1
0
-9
-9
>> logical([3 2 0 12.4 0])
ans =
1
1
0
1
0
0
0
>> a(b)
ans =
-1
0
1
>> a(a<2)
ans =
-1
0
1
>> a(logical([1 0 1 1]))
ans =
-1
2
3
>> a(a>0)=-9
a =
-1
0
-9
-9
3
find() 函數的使用
>> a=[1 2 3 6;3 2 1 1;9 3 7 0]
a =
1
2
3
6
3
2
1
1
9
3
7
0
>> b=(a>=6)
b =
0
0
0
0
1
0
0
0
1
1
0
0
>> find(b)
ans =
3
9
10
>> [r,c]=find(a>=6)
r =
3
3
1
c =
1
3
4
>> find([0 2 0;0 1 0;0 0 0])
ans =
4
5
4
邏輯運算子
>> 4&0
ans =
0
>> [1 0 3] | [2 0 0]
ans =
1
0
1
>> ~[0 2 2 5 0]
ans =
1
0
0
0
1
5
all() 與any()函數
>> any([1 2 0 0 0])
ans =
1
>> all([1 2 0 0 0])
ans =
0
>> any([0 0 0])
ans =
0
>> a=[1 2 3;0 3 2;3 0 1]
a =
1
2
3
0
3
2
3
0
1
>> all(a)
ans =
0
0
>> all(all(a))
ans =
0
1
6
性質測試函數
7
性質測試函數的範例
>> isempty([])
ans =
1
>> isfloat(uint8(5))
ans =
0
>> isequal([1 2 3 4],[1 2 3 0])
ans =
0
>> isnumeric(uint8(5))
ans =
1
>> isfloat(5)
ans =
1
>> isscalar(3)
ans =
1
>> isscalar([3 3])
ans =
0
8
選擇性敘述 if-elseif-else
%script9_1.m
if 5>3
disp('5大於3')
end
>> script9_1
5大於3
function func9_1(num)
if mod(num,2)==0
fprintf('%g是偶數\n',num)
else
fprintf('%g是奇數\n',num)
end
>> func9_1(12)
12是偶數
>> func9_1(35)
35是奇數
>> func9_1(3.6)
3.6是奇數
9
修正func9_1() 的問題
function func9_2(num)
if num-fix(num)==0 & num>0
if mod(num,2)==0
fprintf('%g是偶數\n',num)
else
fprintf('%g是奇數\n',num)
end
else
fprintf('%g不是正整數\n',num)
end
第二行的fix() 可用來取出數值的整數
部份。若num-fix(num)的結果為0,代
表num並沒有小數部分,所以可藉此
來判定輸入的引數num是否為整數。
>> func9_2(12)
12是偶數
>> func9_2(12.44)
12.44不是正整數
>> func9_2(13)
13是奇數
10
if-elseif-else敘述
function func9_3(num)
if isinteger(num)
disp('傳入的引數是n-bit整數')
elseif islogical(num)
disp('傳入的引數是邏輯型態')
elseif isfloat(num)
disp('傳入的引數是浮點數')
else
disp('傳入的引數是其它型態')
end
>> func9_3(logical(1))
傳入的引數是邏輯型態
>> func9_3(3.4)
傳入的引數是浮點數
>> func9_3(uint8(1))
傳入的引數是n-bit整數
>> func9_3('a string')
傳入的引數是其它型態
11
使用switch-case-otherwise指令
12
switch指令的應用
function func9_4(method)
switch method
case {'linear','bilinear'}
disp('linear/bilinear
method')
case 'cubic'
disp('Cubic method')
otherwise
disp('Unknown method')
end
function test=func9_5(num)
n=mod(num,2);
switch n
case 1
test=logical(0);
case 0
test=logical(1);
otherwise
disp('not a positive integer')
test=logical(0);
end
>> func9_4('bilinear')
linear/bilinear method
>> func9_5(12)
ans =
1
>> func9_4('newton')
Unknown method
>> func9_5(11)
ans =
0
>> func9_5(12.22)
not a positive integer
ans =
0
13
for迴圈
%script9_2.m
total=0;
for num=2:100
if isprime(num)
total=total+num;
end
end
fprintf('sum=%d\n',total)
>> script9_2
sum=1060
>> sum(primes(100))
ans =
1060
14
for迴圈的範例
%script9_3.m
a=magic(5);
b=zeros(5); %把5x5的全零陣列設定給變數b
for i=1:5
for j=1:5
if isprime(a(i,j))
b(i,j)=a(i,j);
end
end
end
disp(b) % 顯示陣列b的內容
>> magic(5)
ans =
17
24
1
8
15
23
5
7
14
16
4
6
13
20
22
10
12
19
21
3
11
18
25
2
9
>> script9_3
17
0
0
0
0
23
5
7
0
0
0
0
13
0
0
0
0
19
0
3
11
0
0
2
0
%script9_4
for i=[1 2;3 4]
i %於指令視窗內印出變數i的值
end
>> script9_4
i =
1
3
i =
2
4
15
使用while迴圈
%script9_5.m
total=0;
num=2;
while num<=100
if isprime(num)
total=total+num;
end
num=num+1;
end
fprintf('sum=%d\n',total)
>> script9_5
sum=1060
>> sum(primes(100))
ans =
1060
%script9_6.m
total=0;
num=2;
cnt=0;
while cnt<100
if isprime(num)
total=total+num;
cnt=cnt+1;
fprintf('%3d: prime=%3d,
sum=%5d\n',cnt,num,total)
end
num=num+1;
end
>> script9_6
1: prime= 2, sum=
2
2: prime= 3, sum=
5
...
100: prime=541, sum=24133
16
使用break 與continue指令
17
while迴圈/break/continue
%script9_7.m
num=1000;
while 1
if isprime(num)
break
else
num=num+1;
end
end
fprintf('大於1000的最小質數為%3d\n',num)
>> script9_7
大於1000的最小質數為1009
%script9_8.m
for num=1:20
if isprime(num)
continue
end
fprintf('%3d',num)
end
fprintf('\n')
>> script9_8
1 4 6 8 9 10 12 14 15
16 18 20
18
迴圈執行效率的探討 /計時指令
• Matlab以 tic 和 toc 做為計時指令
• tic和toc的發音就類似按下碼錶與放開時的聲音
>> tic,sum(sqrt(1:10^7)),toc
ans =
2.1082e+10
Elapsed time is 0.142524 seconds.
>> tic,length(primes(2^26)),toc
ans =
3957809
Elapsed time is 0.913899 seconds.
19
將迴圈向量化
100
利用迴圈計算加總
1

2
n 1 n  1
%script9_9.m
total=0;
for n=1:100
total=total+1/(n^2+1);
end
total
% 顯示執行的結果
迴圈的執行內容向量化
>> n=1:100; sum(1./(n.^2+1))
ans =
1.0667
>> script9_9
total =
1.0667
20
將迴圈向量化
• 分別利用迴圈與向量化的程式碼撰寫加總
%script9_10.m
tic
total=0;
for i=linspace(1,2*pi,10^6)
total=total+sin(i)/log2(i)^log(i);
end
toc
>> script9_10
Elapsed time is 1.007577 seconds.
sin(i )
i (log i)log(i )
2
%script9_11.m
tic
i=linspace(1,2*pi,10^6);
sum(sin(i)./log2(i).^log(i))
toc
>> script9_11
ans =
1.9158e+005
Elapsed time is 0.088098
seconds.
21
預先配置記憶空間給陣列
• 預先配置記憶空間給陣列可加快程試執行的速度
%script9_13.m
tic
clear a;
for i=1:500000
a(i)=sin(i)+cos(i);
end
toc
%script9_14.m
tic
a=zeros(1,500000); %預先配置記憶空間
for i=1:500000
a(i)=sin(i)+cos(i);
end
toc
>> script9_13
Elapsed time is 0.144187
seconds.
>> script9_14
Elapsed time is 0.028644 seconds.
22
Exercises(1/2)
• 試撰寫一函數,可接收某個人的身高與體重,接
著完成下列問題:
(a)計算此人的身體質量指數BMI值(BMI=體重(公
斤)/身高(公尺)^2)。
(b) 根據BMI值判斷他的體重是不是過重。理想體
重範圍為18.5≦BMI<24,當BMI值為理想體重範
圍時,印出 ‘體重標準’。BMI值若是小於18.5,印
出 ‘體重過輕’,BMI值若是大於等於24,印出 ‘體
重過重’。
23
Exercises(2/2)
• 試撰寫一個函數,利用for迴圈計算下列數
列的總和:
n
i 1 2
2
2
2
n 1 2
(

1
)
i

1

2

3

4



(

1
)
n

i 1
• 試以迴圈向量化的方式改寫上題函數,並
輸入較大的數值n(例如:n=1000)來測試二
種方式的效率。
24