1

הוראות בקרה – control statements

נבחין בין שני סוגי הוראות בקרה:

הוראות "בחירה" - באמצעותן בוחרים אחת, מבין כמה קבוצות של הוראות, כדי לבצע אותה.

ב Matlab, קיימות שתי הוראות מסוג זה : if ,ו- switch. לכל אחת מהן צמודות אחת או יותר קבוצות של הוראות, ומנגנון לבחירת אחת מהן לביצוע.

לולאות - אלה הוראות בקרה שמאפשרות חזרה על קבוצה אחת של הוראות, מספר מבוקר של פעמים. ההוראות שאמונות על סוג זה של בקרה הן הלולאות for, while. השוני ביניהן הוא באופן הבקרה על הלולאה.

Conditional Control בקרה על פי תנאי, ההוראה if

התצורה הפשוטה ביותר של ההוראה if, שכוללת ביטוי- שמשמש כתנאי - וקבוצת פקודות. אם ערך הביטוי הוא true, אזי מתבצעות הפקודות statements :

if expression

statements

end

מילת המפתח end מסיימת את ההוראה, ומן הסתם גם "סוגרת" את קבוצת הפקודות.

תנאי לוגי יכול להיות "פשוט" כגון:

(a>7)

או מורכב יותר, שמכיל קשרים לוגים (logical connectives), כמו :

(a>7 && b*a~=12)

ב Matlab גם ביטוי מספרי יכול לשמש כתנאי: ערך שונה מאפס יחשב כ-true (1), ואפס יחשב כ- false, (0). דוגמאות:

if (x>y)

tmp=y;

y=x;

x=tmp;

end

או:

if(fix(a/7))

a=a+1;

b=a*pi;

end

(fix(a) מעגלת את a אל השלם הקרוב בכיוון ה- 0)

מילת המפתח else

ל - if יש מספר תצורות. תצורה נוספת כוללת תנאי ושתי קבוצות של פקודות. אם ערך התנאי הוא true, מתבצעת הקבוצה הראשונה, ואם false, השנייה. מילת המפתח else מפרידה בין שתי הקבוצות :

if expression

statements1

else

statements2

end

כאן מנצלים את שני הערכים האפשריים של התנאי, ולא רק את ה- true.

דוגמא:

a=12;

b=sin(35);

if (a/b>pi)

c=2*pi;

d=cos(12*c-a);

b=b^2;

else

c=pi/4;

d=tan(10*c-b);

end

disp(c)

disp(d)

תצורה נוספת עם מילת המפתח elseif משמשת להפרדה בין הקבוצות, וכדי "למקם" את התנאים הללו. נראה מבנה עם שלושה תנאים לוגיים וארבעה קבוצות של פקודות:

if expression1

statements1

elseif expression2

statements2

elseif expression3

statements3

else

statements4

end

דוגמא:

a=12;

b=sin(35);

if (a/b>pi)

c=2*pi;

d=cos(12*c-a);

b=b^2;

elseif(a/b+1>pi)

c=2.1*pi;

d=cos(12.5*c-a);

b=b^3;

elseif(a/b+1.5>pi)

c=2.3*pi;

d=cos(13.5*c-a);

b=b^3.2;

else

c=2.5*pi;

d=cos(14.5*c-a);

b=b^3.5;

end

disp(c)

disp(d)

disp(b)

ניתן לכונן (nesting)מספר כלשהו של הוראות if. דוגמא:

if (a>b)

c=a-b;

if (c/a<2)

c=c+2;

end

else

if(a>b+1)

c=2*a-b/3;

else

c=3*b+a/2;

end

end

לנוחות העבודה בחלון הפקודות : את הוראת ה- if ניתן גם לרשום בשורה אחת, אם נפריד בין הרכיבים שלה על ידי פסיקים או semicolons. למשל, במקום לרשום כך :

>> if(pi>1)

disp(1)

i=5;

disp(3)

end

נוכל לרשום את אותה הוראה בשורה אחת:

>> if(pi>1), disp(1), i=5; disp(3), end

1

3

כזכור, הוספת סימן ה semicolon אחרי פקודה מונע את הדפסת התוצאה שלה.

אם ערך ביטוי התנאי של ההוראה הוא מבנה, הוא יחשב ל true, רק אם כל אבריו שונים מאפס. למשל נניח ש A הינה מטריצה. אזי המבנה :

if A

statements

end

שקול למבנה :

if all(A(:))

statements

end

אם ערך ביטוי התנאי הוא מטריצה ריקה, אזי זו נחשבת ל false. דוגמא:

>> if([])

disp(1)

else

disp(2)

end

2

חומר למחשבה:

התנאים יכולים גם להיות בין מבנים, נראה מקרה מעניין שבו מבצעים פעולת OR בין שני וקטורים באורכים שונים, וזה עובד ! :

>> a

a =

1 2 3 4

>> d

d =

1 2 3 4 5 6

>> if(a|d),disp(1),else, disp(0),end

1

גם זה יעבוד:

d =

1 0 0 0 0 0

>> if(a|d),disp(1),else, disp(0),end

1

אבל אם נחליף מקומות בין אותם a ל- d בביטוי הלוגי, זה כבר לא יעבוד:

>> if(d|a),disp(1),else, disp(0),end

??? Error using ==> or

Inputs must have the same size.

ומה עם הOR המקוצר, "||" על אותם וקטורים ?

>> if(a||d),disp(1),else, disp(0),end

??? Operands to the || and && operators must be convertible to logical scalar values.

המקוצר אינו עובד.

כעת נבדוק את ה AND הרגיל :

>> b=[1 2 3 4 5];

>> c=[1 1 1];

>> if(c&b),disp(1),else, disp(0),end

??? Error using ==> and

Inputs must have the same size.

ולגבי AND מקוצר מקבלים הערה אחרת:

>> if(c&&b),disp(1),else, disp(0),end

??? Operands to the || and && operators must be convertible to logical scalar values.

כל הדברים הללו נכונים גם עבור הלולאה while בהמשך.

expression Control - בקרה על פי ערכים של ביטוי, ההוראה switch

בחירת הקבוצה נעשית לפי ערך של ביטוי אחד. המבנה הכללי של ההוראה הוא:

switch switch_expression

case case_expression1

statement, ..., statement

case {case_expression i,…, case_expression j}

statement, ..., statement

otherwise

statement, ..., statement

end

הביטוי switch_expression יכול להיות סקלר, או מחרוזת.

באמצעות מילת המפתח case, "מצמידים" לכל קבוצת פקודות, ערך אחד, או כמה ערכים אפשריים של ה - switch_expression. ערכים אלה מופיעים במבנה הקודם כ:

case_expressioni,… case_expressionj,…

הקבוצה שתתבצע היא זו "שצמודה" לערך שהתקבל בחישוב הביטוי switch_expression.

למשל, כדי שקבוצת הפקודות k תתבצע , אזי :

- אם תוצאת הביטוי היא סקלר, חייב להתקיים:

switch_expression==case_expressionk

- ואם התוצאה היא מחרוזת, הפונקציה הבאה חייבת להחזיר true (logical 1):

strcmp(switch_expression, case_expressionk)

אם ערך הביטוי switch_expression, אינו נמצא באף case, תתבצע קבוצת הפקודות שמופיעה אחרי מילת המפתח otherwise, אם יש כזאת. השימוש ב- otherwiseהוא אופציונאלי.

דוגמא, נשמור את ה switch הבא בקובץ script בשם sw, ואחר כך נפעיל את ה script:

switch (x)

case {1,2}

disp('2 elements vec'),[1 2].^x

case 3

disp('3 elements vec'),[1 2 3].^x

case 4

disp('4 elements vec'),[1 2 3 4].^x

otherwise

disp('rand answer'),rand(1,5).^x

end

אם נפעיל את sw על קלטים שונים, נקבל:

>> x=1;

>> sw

2 elements vec

ans =

1 2

>> x=2;

>> sw

2 elements vec

ans =

1 4

>> x=4;

>> sw

4 elements vec

ans =

1 16 81 256

>> x=6;

>> sw

rand answer

ans =

0.2925 0.5523 0.0000 0.5806 0.0639

בקרת לולאות – for,while,continue,break

הלולאה for

המבנה הכללי של ההוראה for הוא :

for index = index_range

statements

end

כאשר index הוא משתנה הלולאה, ו- index_range טווח הערכים שלו.

נבחין בין מספר תצורות: נראה תחילה מקרה שבו index הוא סקלר ו index_range הוא וקטור y בעל n איברים:

for index = y % y vector of n members

statements

end

הלולאה הזאת תתבצע n פעמים, הערך ההתחלתי של index יהיה y(1), אחריו y(2), וכו". הערך האחרון הוא y(n). נראה דוגמא עם וקטור כלשהו :

for index = [2 4 -1 21]

v(index +2)=index *v(index +4);

end

כאן המשתנה index יקבל לפי הסדר, את ערכו של כל אחד מאברי וקטור-הטווח.

את וקטור הטווח אפשר להגדיר גם על ידי אופרטור ה colon :

for index = start:increment:end

statements

end

index הוא משתנה הלולאה, וindex_range- הוא וקטור "חצי אוטומטי".

דוגמא :

for ind = 3:2:8

v(ind) = v(ind - 1)/2;

u(ind)= u(ind-1)-5;

end

כאן ind קיבל את הערכים : 3,5,7.

for ind = 8:-2:-1

v(ind+1) = 2.5 * v(ind+2);

u(ind+1)= u(ind+2)-5;

end

וכאן הוא קיבל את הערכים 8,6,4,2,0.

אם מעוניינים בגישה לוקטור הלולאה , יש להגדירם ולשמור אותם במשתנה לפני כניסה ללולאה:

>> k=11:-6:-8;

>> for i=k,disp(i),end

11

5

-1

-7

נחזור למבנה הכללי:

for index = index_range

statements

end

כאשר ה- index_range הוא מטריצה ,A nxm, ה index יהיה בכל איטרציה וקטור עמודה אחר של A .הלולאה הזאת תתבצע m פעמים - כמספר עמודות A.

לולאות for מכוננות nested for loops-

ניתן לכונן שתים או יותר לולאות for אחת בתוך השנייה:

for i = [5 1 11 4 2]

for j = [3 1 4 2]

B(i, j) = 1/(i^j)-1/(j^i);

end

end

הלולאה while

הלולאה while חוזרת ומבצעת קבוצת פקודות, כל עוד ערך ביטוי התנאי שלה, הוא true.

while while_expression

statements

end

אם ערך הביטוי הוא מטריצה, אזי כדי שהלולאה תמשיך, כל אברי המטריצה חייבים להיות שווים ל- 1.

דוגמא מאד לא יעילה: עבור איזה n, סכום אברי הוקטור 1:n, עובר את ה- 1000:

n = 1;

while sum(1:n) < 1000

n = n + 1;

end

n-1

הדוגמא לא יעילה מכיוון שבכל איטרציה מחשבים שוב את הסכום מהתחלה, במקום להשתמש בסכום הקודם.

גם לולאות while ניתנות לכינון. דוגמא:

while (a>7)

disp(a)

a=a+1;

b=b-1;

while(a>b)

disp(b)

b=b+1;

a=a-1;

end

end

ניתן לכתוב לולאת while על שורה אחת, אם משתמשים בפסיקים וב semicolons-:

>> i=0;

>> while(i<pi),disp(i),disp(2*i),i=i+1.5;end

0

0

1.5000

3

3

6

לולאת while מפסיקה כאשר ערך ביטוי התנאי שלה הוא false, או אפס, או מטריצה ריקה.

ההוראות continue, break

ההוראה break מפסיקה ביצוע של הלולאה שהיא כלולה בה. דוגמא:

while (a>9)

disp(a)

a=a+1;

b=b-1;

while(a>b)

disp(b)

b=b+1;

a=a-1;

if(a==b)

break;

end

end

end

ההוראה continue מפסיקה את האיטרציה הנוכחית שלה, וחוזרת לשורת הבקרה של הלולאה. דוגמא:

for ind=[6 3 5 2 3 1]

disp(ind+a-b)

a=a+1;

b=b-1;

for ind1=[1 3 2 4 3 5]

disp(ind1-b+a)

b=b+1;

a=a-1;

if(ind==ind1-a)

continue;

end

end

end

continue בתוך לולאה מכוננת, מפסיקה רק את האיטרציה של הלולאה שהיא כתובה בה.

הפקודות if ו-switch אינן לולאות, ולכן לא break , ולא continue יעבדו בתוכן, אלא אם אלה ימצאו בתוך לולאה:

>> if(a>3),disp(a),else,break,end

??? Error: A BREAK statement appeared outside of a loop. Use RETURN instead.

>> switch(3),case 2,break,end

??? Error: A BREAK statement appeared outside of a loop. Use RETURN instead.

>> if(a>3),disp(a),else,continue,end

??? Error: A CONTINUE may only be used within a FOR or WHILE loop.

אבל כאשר ה-if בתוך לולאה זה עובד:

>> for i=4:-1:3,if(i>3),disp(a),else,break,end,end

5

"מתוך הספר: Matlab - מדריך טיולים"

©כל הזכויות שמורות לאריה שלזינגר,2008