Download presentation
Presentation is loading. Please wait.
1
Chapter 5 Controlling the flow of your program
5.1 Choice and decision-making 5.2 Logical expressions and LOGICAL variables 5.3 The block IF construct 5.4 The logical IF statement 5.5 Comparing character strings 5.6 The CASE construct 5.7 Obsolete forms of control statements
2
5.1 Program executes alternative instructions depending on conditions:
Block IF construct: E.g. For x >= 0 : IF(ABS(x) < 1.E-20) THEN cube_root =0.0 ELSE cube_root = EXP(LOG(x)/3.0 ) ENDIF Note: |X| in F90 is ABS(X) X 1/3 = elog(x)/3
3
5.1 Fortran 90 alternatives: IF (criterion_1) THEN action_1
ELSE IF (criterion_2) THEN action_2 ELSE IF (criterion_3) THEN action_3 ELSE action_4 END IF A minimal block IF: IF (criterion) THEN action
4
5.2 Logical expressions and LOGICAL variables
-Logical values are true or false: In FORTRAN 90: .TRUE. .FALSE. are the constants for true or false. -Logical expressions e.g. L = a > b !e.g. true for a=3, b=1 x= =y ! e.g false for x =3, y =1 Also, are called ‘relational expressions’ and ‘ > ’ , ‘= =‘ are ‘relational operators’.
5
5.2 (2) Relational operators and expressions:
a < b and a .LT. b are true if a is less than b a <= b and a .LE. b are true if a is less than or equal to b a > b and a .GT. b are true if a is greater than b a>=b and a .GE. B are true if a is greater than or equal to b a == b and a .EQ. b are true if a is equal to b a /= b and a .NE. b are true if a is not equal to b Redundancy in using operators for log. Expression of the same condition: e.g b**2 >= 4*a*c b**2-4*a*c >= !e.g. TRUE for b =5, a =2, c =3 4*a*c <= b**2 4*a*c-b**2 <= 0
6
5.2 (3) -Also rel. operator’s can express relation between char. expressions: e.g: string_1 <= string_2 “Adam” <= “Eve” ! True LOGICAL var’s : LOGICAL :: var_1, var_2, var_3 e.g: var_1 = (a > b) const’s .TRUE. , .FALSE. Write functions which deliver a logical value: LOGICAL FUNCTION logical_fun (arg1, ...) . or FUNCTION logical_fun (arg1, ...) LOGICAL :: logical_fun
7
5.2 (5) Form composite logical expressions using .OR. , .AND. ‘logical operators’: e.g (a<b) .OR. (c<d) or (x<=y) .AND. (y<=z) ‘(‘ , ‘)’ can be omitted e.g a<b .OR. c<d ! But may confuse us; so use ‘(‘ , ‘)’ (a<b) .OR. (c<d) e.g. a = 2 , b = 3 , c = 5 , d = 3 => value of log. expr. = .TRUE.
8
5.2 (6) The logical operators .OR. and .AND. L1 L2 L1.OR.L2 L1.AND.L2
true true true true true false true false false true true false false false false false e.g. L1 = (a < b) !as above L2 = (c < d) !as above L1. OR .L2 = .TRUE. L1. AND .L2 = .FALSE The logical operators .EQV. and .NEQV.. L1 L2 L1.EQV.L2 L1.NEQV.L2 true true true false true false false true false true false true false false true false
9
5.2 (7) .EQV. If both expressions have the same value, else
.NEQV. .=> useful to simplify structure of the expressions: The following two expressions are identical in their effect: L L L L4 e.g. (I) (a<b .AND. x<y) .OR. (a>=b .AND. x>=y) ex ex2 (II) a<b .EQV. x<y L L2 The explanation for this follows by writing the truth Table for each (I) and (II) and checking that the same ‘T’ , ‘F’ occur in all cases: (e.g. L1= 2<3 ; L2= 5<8 )
10
5.2 (7’) L1 L2 ex1 L3 L4 ex2 (I) (II) T F
11
5.2 (8) . NOT. is a unary operator gives .TRUE. for value .FALSE.
and vice-versa e.g. The following expressions are equivalent in their effect: (I) .NOT. (a<b .AND. b<c) !e.g. a = 2 , b = 3 (II) a>=b .OR. b>=c ! c = 5 And, of course (I) .NOT. (a<b .EQV. x<y) (II) a<b .NEQV. x<y .NOT. Helps clarify expressions . (a+b) < (c+d) .Order : 1st : arithmetic operators (e.g. *, +, etc) ; 2nd: relational operators (e.g. < , = = etc); 3rd: logical operators
12
5.2 (9) Logical operator priorities: Operator Priority . NOT. highest
. NOT. highest .AND. .OR. .EQV. and .NEQV. lowest
13
5.3 The block IF construct The block IF construct is:
IF (logical_expression) THEN ELSE IF (logical_expression) THEN e.g. IF(.NOT. (a < b. AND. b < c)) X = a + b ELSE IF (a < b. AND. b < c) X = c + b ENDIF
14
5.3 (3) The block IF structure: IF (logical expression) THEN
block of Fortran statements ELSE IF (logical expression) THEN . ELSE END IF
15
5.3 (4) EXAMPLE 5.1 (1) Problem Example 4.1 calculated the number of bags of wheat that were required to sow a triangular field. 2s = a + b + c => area = (s(s-a)(s-b)(s-c))1/2 Use IF statement for no. of full bags needed to sow the field. Analysis: quantity(of wheat) = area * density => no. of bags = quantity / 10, (to allow for partly used bag). Better way use ‘IF’
16
5.3 (5) (2) Structure Plan 1 Read lengths of sides of field (a, b and c) 2 Calculate the area of the field 3 Read the sowing density 4 Calculate the quantity of seed required 5 Calculate number of full bags needed 6 If any more seed is needed then 6.1 Add one to number of bags 7 Print size of field and number of bags
17
5.3 (6) (3) Solution (p139.f) PROGRAM wheat_sowing IMPLICIT NONE
! A program to calculate the quantity of wheat required to ! sow a triangular field ! Variable declarations REAL :: a, b, c, s, area, density, quantity INTEGER :: num_bags ! Read the lengths of the sides of the field PRINT *, "Type the lengths of the three sides of the field & &in meters: " READ *, a, b, c
18
5.3 (7) ! Calculate the area of the field s = 0.5*(a+b+c)
area = SQRT(s*(s-a)*(s-b)*(s-c)) ! Read sowing density PRINT *, "What is the sowing density (gm/sq.m.)? " READ *, density ! Calculate quantity of wheat in grams and the number of ! full 10 kg bags quantity = density*area num_bags = *quantity !partly-full bag is excluded: (i) ! In section 4.1: num_bags =0.0001*quantity+0.9! To round up
19
5.3 (8) ! Check to see if another bag is required
IF (quantity > 10000*num_bags) THEN ! (ii) num_bags = num_bags+1 END IF ! Print results PRINT *, "The area of the field is ", area, " sq. meters" PRINT *, "and ", num_bags, " 10 kilo bags will be required" END PROGRAM wheat_sowing
20
5.3 (9) NOTE: 1. In (i), num_bags is INTEGER and quantity is REAL
2. In (ii), quantity > * num_bags is converted to REAL (quantity * num_bags ) > 0.0 3. Accuracy of real arithmetic : recall REAL no’s are stored as approximations in the computer e.g. with 6 significant figures is stored as OR Also in operations e.g Rounding in hand calculation(Fig5.10) : 25.39 * = = If 7-th digit = 0,..,4 truncate from 7-th digit on. If 7-th digit = 5,..,9 add 1 to 6-th digit & truncate from 7-th digit on 4. Computer rounding is similar. Recall e.g. Fig.3.3 Mantissa or fraction exponent form: = *103 = exp fraction
21
5.3 (10) For no’s in Fig.5.10 : = * 102, = * 102 and 25.39*17.25 = * 103 = *103 5.The no. of digits in the fractions allowed(e.g in the example is: 6) is called precision. Real type has 24 bits = 7 or 8 decimal digits. ‘DOUBLE PRECISION’ type (in chapter 10) allows 14 or 15 decimal digits. 6. In REAL & INTEGER expressions INTEGER are converted to REAL e.g. (Chapter 3) a = b*c/d (b =100.0, c =9, d =10) => b*c =900.0 => 90.0 BUT a= c/d*b => (c/d =0, INTEGER division) => a =0.0 7. (a) For (i): Convert REAL to INTEGER before storing result. (b) For (ii): compare or subtract 2 real no’s which are almost equal e.g. Farm field sides: a=130,m =c, b=100m, density =25g/m2 =>area =6000m2 => 150kg seed => num_bags =15
22
In computer possibly : area =5 999.999 999 or = 6000.000 001
=>num_bags=.0001*quantity= OR which is approx = 15 BUT if we simply truncate to get INTEGER we get 14 or 15; if We compute 10000*num_bags and e.g. quantity = then if (quantity-10000*num_bags)>0.0 is .TRUE. => 16 bags. To allow for (round) errors less than 10% write prog: REAL Mixed: (INTEGER,REAL) IF (quantity > 10000*num_bags+1000) THEN num_bags = num_bags + 1 END IF
23
5.3 (11) OR BETTER avoid num_bags: REAL REAL REAL
IF (0.0001*quantity - INT(0.0001*quantity) > 0.1) THEN num_bags = num_bags + 1 END IF e.g. INT(150, ) = 150,000
24
5.3 (12) EXAMPLE 5.2 (1) Problem Write an external function for X1/3
(2) Analysis We have done X1/3 = cube root = EXP(LOG(X))/3.0) for X > 0 Need (-X)1/3 = -(X)1/3 for X >0 and (0)1/3 = 0 special case because Log(X) undefined for X =0
25
Data design Purpose Type Name A Dummy argument: Value whose cube REAL x root is required B Result variable: Cube root of x REAL cube_root C Local constant: A very small number REAL epsilon e.g. = 1E-10
26
5.3 (13) Structure plan Real function cube_root(x) 1 If
1 If 1.1 Return zero else of x<0 1.2 Return –exp(log(-x)/3) else 1.3 Return exp(log(x)/3)
27
5.3 (14) (3) Solution (p143.f) REAL FUNCTION cube_root(x)
IMPLICIT NONE ! Function to calculate the cube root of a ! real number ! Dummy argument declaration REAL, INTENT(IN) :: x ! Local constant REAL, PARAMETER :: epsilon=1.E-10
28
5.3 (15) ! Eliminate (nearly) zero case IF (ABS(x)<epsilon) THEN
cube_root = 0.0 ! Calculate cube root by using logs ELSE IF (x<0) THEN ! First deal with negative argument cube_root = -EXP(LOG(-x)/3.0) ELSE ! Positive argument cube_root = EXP(LOG(x)/3.0) END IF END FUNCTION cube_root
29
5.3 (16) EXAMPLE 5.3 Problem Modify the subroutine line_two_points, so that it returns an error flag to indicate that either (a) the two points were distinct, and the equation of the joining line was therefore calculated, or (b) it was not possible to calculate the line because the points were coincident.
30
5.3 (17) (2) Analysis Need: logical error flag for equal points; Return STATUS =0 for distinct pts and STATUS = -1 otherwise Structure plan Subroutine line_two_points(line_1, point_1, point_2, status) TYPE(line) :: line_1 TYPE(point) :: point_1, point_2 INTEGER :: status 1 If point_1 and point_2 are coincident 1.1 Set status to –1 Else 1.2 Calculate coefficients of the line joining the points 1.3 Set status to 0
31
5.3 (18) (3) Solution (p144.f) MODULE geometric_procedures
USE geometric_data IMPLICIT NONE CONTAINS SUBROUTINE line_two_points(line_1,point_1,point_2,status) IMPLICIT NONE ! Dummy arguments TYPE(Line), INTENT(OUT) :: line_1 TYPE(Point), INTENT(IN) :: point_1,point_2 INTEGER :: status
32
5.3 (19) ! Check whether points are equal, using ABS(). e.g. for x coord: Take ! epsilon = 1.E-10 and IF( ABS(point_1%x - point_2%x ) < epsilon IF (point_1%x==point_2%x .AND. point_1%y==point_2%y) THEN ! Points are coincident - return error flag status = -1 ELSE ! Points are distinct, so calculate the coefficients ! of the equation representing the line line_1%a = point_2%y - point_1%y line_1%b = point_1%x - point_2%x line_1%c = point_1%y*point_2%x - point_2%y*point_1%x ! Set status to indicate success status = 0 END IF END SUBROUTINE line_two_points END MODULE geometric_procedures
33
5.4 The logical IF statement
The logical IF statement omits ‘THEN’ : IF (logical expression) Fortran statement e.g. IF(quantity > 10000*num_bags) num_bags = num_bags+1 This is exactly equivalent to a block IF with a block consisting of a single statement: IF (logical expression) THEN Fortran statement END IF
34
5.5 Comparing character strings
The six relational operators could be used to compare character expressions and constants. e.g. “Adam” > “Eve” ! ? True The key is the collating sequence of letters, digits and other characters. Six rules: (1) The 26 upper case letters are collated in the following order: A B C D E F G H I J X L M N 0 P Q R S T U V W X Y Z (2) The 26 lower case letters are collated in the following order: a b c d e f g h i j k 1 m n o p q r s t u v w x y z (3) The 10 digits are collated in the following order:
35
5.5 (2) (4) Digits are either all collated before the letter A, or all after the letter Z (5) Digits are either all collated before the letter a, or all after the letter z (6) A space (or blank) is collated before both letters and digits The other 22 characters in the Fortran character set do not have any defined position in the collating sequence.
36
5.5 (3) When two character operands are being compared there are
three distinct stages in the process: If the two operands are not the same length, the shorter one is treated as though it were extended on the right with blanks. (2) The two operands are compared character by character, starting with the leftmost character. If a difference is found the character which comes earlier in the collating sequence being deemed to be the lesser of the two. If no difference is found, then the strings are considered to be equal.
37
5.5 (4) e.g. “Adam” > “Eve” !False “Adam” < “Eve” !True
“Adam” < “Adamant” !True “ “ < “a” “120” < “1201” !True “ “ < “1” “ADAM” < “Adam” !Not defined : “D” “d” “ XA” < “ X4” !Not defined : “A” “4” “var_1” < “var-1” !Not defined : “_” “-” NOT a problem, because strings are compared usually (?) if they are equal e.g. “XA” = = “X4” !False
38
5.5 (5) FORTRAN 90 does not define whether upper case letters come before or after lower case letters. The value of s1="ADAM" < s2="Adam" will depend upon the particular computer system being used. There are intrinsic functions which use the ASCII char’s order to decide the order of strings Intrinsic functions for lexical comparison: LGT(sl, s2) is the same as sl > s2 using ASCII character ordering. LGE(sl, s2) is the same as sl >= s2 using LLE(sl, s2) is the same as sl <= s2 using LLT(sl, s2) is the same as sl < s2 using
39
5.5 (6) If it is required to define the ordering of all characters, another way of comparing uses the ordering of characters defined in the American National Standard Code for Information Interchange referred to as ASCII.(Appendix D, p. 727) e.g. in Fortran: “Miles” > “miles” is undefined. But LGT (“Miles”,”miles”) = .FALSE. (because “M” before “m” in ASCII)
40
5.5 (7) EXAMPLE 5.4 (SKIPPED, not in exams) (1) Problem
Write a function which takes a single character as its argument and returns a single character according to the following rules: If the input character is a lower case letter then return its upper case equivalent. If the input character is an upper case letter then return its lower case equivalent. If the input character is not a letter then return it unchanged.
41
5.5 (8) (2) Analysis IACHAR provides the position of its character argument in the ASCII collating sequence ACHAR returns the character at a specified position in that sequence. Every lower case character is exactly 32 positions after its upper case equivalent. Use intrinsic functions IACHAR(“A”) = 65 (=position in ASCII) ACHAR(97) = a. Note: position (in ASCII) of lower case letter – position (in ASCII) of upper case letter =32 e.g. IACHAR(“a”) – IACHAR(“A”) = = 32
42
5.5 (9) e.g. A –> a, change_case =ACHAR(IACHAR(“A”)+32)=
ACHAR(65+32) = ACHAR(97) = “a” a –> A, change_case =ACHAR(IACHAR(“a”)-32)= ACHAR(97-32) = AHAR(65) = “A” Data design: Purpose Type Name A Dummy argument: Character to be CHARACTER*1 char converted B Result variable: Converted character CHARACTER*1 change_case C Local constant: Offset between upper INTEGER upper_to_lower and lower case in the ASCII character set
43
5.5 (10) Structure plan: Character function change_case(char) 1 If A
1.1 Return character upper_to_lower after char in ASCII else if a 1.2 return character upper_to_lower before char in ASCII else 1.3 Return char unaltered
44
5.5 (11) (3) Solution (p150.f) CHARACTER FUNCTION change_case(char)
IMPLICIT NONE ! This function changes the case of its argument (if it ! is alphabetic) ! Dummy argument CHARACTER, INTENT(IN) :: char ! Local constant INTEGER, PARAMETER :: upper_to_lower = IACHAR("a")-IACHAR("A") ! Check if argument is lower case alphabetic, upper case ! alphabetic, or non-alphabetic
45
5.5 (12) IF ("A"<=char .AND. char<="Z") THEN
! Upper case - convert to lower case change_case = ACHAR(IACHAR(char)+upper_to_lower) ELSE IF ("a"<=char .AND. char<="z") THEN ! Lower case - convert to upper case change_case = ACHAR(IACHAR(char)-upper_to_lower) ELSE ! Not alphabetic change_case = char END IF END FUNCTION change_case
46
5.6 The CASE construct The CASE construct deal with many alternatives are mutually exclusive. The CASE structure: SELECT CASE (case expression) CASE (case selector) !mutually exclusive case block of Fortran statements CASE (case selector) !mutually exclusive case . . END SELECT Note: expression is integer, char, logical. But ‘real’ expressions are not allowed.
47
5.6 (2) e.g. CHARACTER(LEN=2):: month
and assume we want to consider the first 6 no’s and the last 6 no’s: SELECT CASE(month) CASE(“01”, “02”, “03”, “04”, “05”, “06”) -statement CASE(“07”, “08”, “09”, “10”, “11”, “12”) END SELECT
48
5.6 (5) EXAMPLE 5.5 (1) Problem Date : yyyy –mm –dd Prog. input : date
Output : what season it is in Australia (2) Analysis Data design: Purpose Type Name Date (yyyy-mm-dd) CHARACTER*10 date Month (for CASE) CHARACTER*2 month
49
5.6 (7) Structure plan: 1 Read date 2 Extract month from date
3 Select case on month 3.1 month is 8, 9 or 10 Print “spring” 3.2 month is 11, 12, 1, 2 or 3 Print “summer” 3.3 month is 4 or 5 Print “autumn” 3.4 month is 6 or 7 Print “winter” 3.5 month is anything else Print an error message
50
5.6 (8) (3) Solution (p155.f) PROGRAM seasons IMPLICIT NONE
! A program to calculate in which season a specified date lies ! Variable declarations CHARACTER(LEN=10) :: date CHARACTER(LEN=2) :: month ! Read date PRINT *, "Please type a date in the form yyyy-mm-dd" READ *, date ! Extract month number month = date(6:7) !
51
5.6 (9) ! Print season SELECT CASE (month) CASE ("08":"10")
PRINT *, date, " is in the spring" CASE ("11", "12", "01":"03") PRINT *, date, " is in the summer" CASE ("04", "05") PRINT *, date, " is in the autumn" CASE ("06", "07") PRINT *, date, " is in the winter" CASE DEFAULT PRINT *, date, " is not a valid date" END SELECT END PROGRAM seasons
52
5.6 (10) Note: CASE(“08”:“10”) is same as CASE(“08”,”09”,”10”) and
EXAMPLE 5.6 (1)Problem :Program with input :coefficients of ax2 + bx +c =0, a/=0 and output : roots e.g. b=-5, a=1, c=6; d = b2 – 4ac = 25 – 4*3*2 = 25 – 24 = 1 > 0 (2) Analysis
53
5.6 (11) Three possible cases: (1) b2 > 4ac (2 distinct REAL roots)
(2) b2 = 4ac (1 REAL root) (3) b2 < 4ac (no REAL root exists) Real arithmetic is only an approximation. We should never compare two real numbers for equality. Thus, we must rewrite the second case (2), as: (2) Epsilon is a very small number. e.g. 1E - 10
54
5.6 (12) If we wish to use a CASE statement, we could dividing the value of b2 - 4ac by epsilon and then assigning the result to an integer for use in the CASE statement. Data design: CASE IF Purpose Type Name A Local constant: A small value REAL epsilon B Local variables: same Coefficients REAL a, b, c Intermediate value REAL d CASE selection value INTEGER selector
55
5.6 (13) Structure plan: 1 Read the three coefficients a, b and c
2 Calculate d = b2-4ac 3 Calculate selector (int(d/epsilon)) 4 Select case on selector: 4.1 selector> (i.e >= 1) Calculate and print two roots 4.2 selector=0 Calculate and print a single root 4.3 selector< (i.e <= -1) Print a message to the effect that that there are no real roots
56
Case: d = 0 d = b2 - 4ac |d/epsilon| < 1 means d = 0 int(d/epsilon) = 0 Case: d > 0 int(d/epsilon) >= 1 Case: d <0 int(d/epsilon) <= -1
57
5.6 (16) (3) Solution (a) Using a CASE construct (p159.f)
PROGRAM quadratic_by_CASE IMPLICIT NONE ! A program to solve a quadratic equation using a CASE ! statement to distinguish between the three cases ! Constant declaration REAL, PARAMETER :: epsilon=1E-10 ! Variable declarations REAL :: a, b, c, d, sqrt_d, x1, x2 INTEGER :: selector
58
5.6 (17) ! Read coefficients PRINT *, "Please type the three coefficients a, b and c" READ *, a, b, c ! Calculate b**2-4*a*c and resulting case selector d = b** *a*c selector = int(d/epsilon) ! Calculate and print roots, if any SELECT CASE (selector) CASE (1:) ! Two roots sqrt_d = SQRT(d) x1 = (-b+sqrt_d)/(a+a) x2 = (-b-sqrt_d)/(a+a) PRINT *, "The equation has two roots: ", x1, " and ", x2
59
5.6 (18) CASE (0) ! One root x1 = -b/(a+a)
PRINT *, "The equation has one root: ", x1 CASE (:-1) ! No roots PRINT *, "The equation has no real roots" END SELECT END PROGRAM quadratic_by_CASE
60
5.6 (19) ‘IF’ solution program Structure plan:
Read coefficients ! -epsilon < d < epsilon 2 Calculate b2-4ac, and store it in d ! means |d| < epsilon 3 If d >= epsilon then ! i.e d= 0 3.1 calculate and print two roots but if d>-epsilon then ! epsilon > d> -epsilon 3.2 Calculate and print a single root 3.3 Otherwise ! d <= -epsilon Print a message to the effect that there are no real roots
61
5.6 (20) (b) The approach using CASE is harder than an block IF construct (p160.f) because we have to find the ‘selector’ in CASE: PROGRAM quadratic_by_block_IF IMPLICIT NONE ! A program to solve a quadratic equation using a block IF ! statement to distinguish between the three cases ! Constant declarations REAL, PARAMETER :: epsilon=1E-10 ! Variable declarations REAL :: a, b, c, d, sqrt_d, x1, x2
62
5.6 (21) ! Read coefficients PRINT *, "Please type the three coefficients a, b and c" READ *, a, b, c ! Calculate b**2-4*a*c d = b** *a*c ! Calculate and print roots, if any IF (d>=epsilon) THEN ! Two roots sqrt_d = SQRT(d) x1 = (-b+sqrt_d)/(a+a) x2 = (-b-sqrt_d)/(a+a) PRINT *, "The equation has two roots: ", x1, " and ", x2
63
5.6 (22) ELSE IF (d<epsilon.AND.d>-epsilon) THEN ! One root
x1 = -b/(a+a) PRINT *, "The equation has one root: ", x1 ELSE IF(d<=-epsilon) ! No roots PRINT *, "The equation has no real roots" END IF END PROGRAM quadratic_by_block_IF
64
5.6 (23) Better: d1 = ABS(d) IF (d1 <= epsilon)THEN !One root
x1 = -b / (a + a) ELSE IF (d < -epsilon)THEN !No roots ELSE !Two roots x1 = x2 = END IF
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.