S
ELECTIVE
E
XECUTION
S
ELECT THE TOPICS YOU WISH TO REVIEW:
Selective ExecutionLOGICAL Type and Variables
LOGICAL Input and Output
Relational Operators
LOGICAL Operators and Expressions IF-THEN-ELSE-END IF Statement Form 1: IF-THEN-ELSE-END IF
Form 2: IF-THEN-END IF
Form 3: Logical IF
Programming Example 1: Quadratic Equation Solver
Programming Example 2: Final Mark Computation
Programming Example 3: Heron's Formula for Computing Triangle Area
Nested IF-THEN-ELSE-END IF
IF-THEN-ELSE IF-END IF Programming Examples: Quadratic Equation Solver: Again
Quadratic Equation Solver: Revisited
Sort Three Numbers
SELECT CASE Statement
Programming Example 1: Computing Letter Grade
Programming Example 2: Character Testing
LOGICAL T
YPE
AND
V
ARIABLES
LOGICAL values are either
true
or
false
. In Fortran, they must be written as .TRUE. and
.FALSE. Note that the two periods surrounding TRUE and FALSE must be there; otherwise,
they become identifiers.
A variable that can hold one of the logical values is a logical variable and it is of type
LOGICAL. To declare a LOGICAL variable, do it as what you did for INTEGER and REAL
variables. But, use the type name LOGICAL instead.
LOGICAL constants can have aliases declared with the PARAMETER attribute.
LOGICAL variables can be initialized when they are declared and can be assigned a logical
value.
However, a
LOGICAL
variable can only hold a logical value. Putting a value of any other type
(
e.g.
,
INTEGER or REAL) into a LOGICAL variable will cause an error.
The following are examples:
Answer, Condition, Test, Value and Yes_and_No are LOGICAL variables that can hold either .TRUE. or .FALSE.:
LOGICAL :: Answer, Condition, Test LOGICAL :: Value, Yes_and_No
LOGICAL identifers Answer and Condition are aliases of .TRUE. and .FALSE., respectively:
LOGICAL, PARAMETER :: Answer = .TRUE., Condition = .FALSE.
LOGICAL variables Test and PreTest are initialized to .TRUE. and .FALSE., respectively:
LOGICAL :: Test = .TRUE., PreTest = .FALSE.
LOGICAL variables Cond_1, Cond_2 and Total are assigned with .TRUE., .TRUE. and .FALSE., respectively:
LOGICAL :: Cond_1, Cond_2, Total
LOGICAL INPUT AND OUTPUT
When using WRITE(*,*) to display a LOGICAL value, Fortran displays .TRUE. and .FALSE.
with T and F, respectively.
When preparing input for READ(*,*), use T and F for .TRUE. and .FALSE., respectively.
RELATIONAL OPERATORS
There are six relational operators:
< : less than
<= : less than or equal to > : greater than
>= : greater than or equal to == : equal to
/= : not equal to Here are important rules:
Each of these six relational operators takes two operands. These two operands must both be arithmetic or both be strings. For arithmetic operands, if they are of diferent types (i.e., one INTEGER and the other REAL), the INTEGER operand will be converted to REAL.
The outcome of a comparison is a LOGICAL value. For example, 5 /= 3 is .TRUE. and 7 + 3 >= 20 is .FALSE.
All relational operators have equal priority and are lower than those of arithmetics operators as shown in the table below:
Type Operator Associati vity
Arithme tic
Relation
This means that a relational operator can be evaluated only if its two operands have
been evaluated. For example, in
a + b /= c*c + d*d
expressions a+b and c*c + d*d are evaluated before the relational operator /= is evaluated.
If you are not comfortable in writing long relational expressions, use parenthesis. Thus,
3.0*SQRT(Total)/(Account + Sum) - Sum*Sum >= Total*GNP - b*b
is equivalent to the following:
(3.0*SQRT(Total)/(Account + Sum) - Sum*Sum) >= (Total*GNP - b*b)
Although a < b < c is legal in mathematics, you cannot write comparisons this way in Fortran. The meaning of this expression is a < b and b < c. You should use logical operator to achieve this.
E
XAMPLES 3**2 + 4**2 == 5**2 is .TRUE.
If the values of REAL variables a, b and c are 1.0, 2.0 and 4.0, respectively, then b*b - 4.0*a*c >= 0.0 is equivalent to 2.0*2.0 - 4.0*1.0*4.0 >= 0.0, which evaluates to -12.0 >= 0.0. Thus, the result is .FALSE.
--> 2.0 /= 228 - [2**3] --> 2.0 /= 228 - 8 --> 2.0 /= [228 - 8] --> 2.0 /= [220] --> 2.0 /= 220.0 --> .TRUE.
In the above, please note the left-to-right evaluation order and the type conversion making 220 to 220.0 before carrying out /=
C
OMPARINGCHARACTER S
TRINGSCharacters are encoded. Diferent standards (e.g. BCD, EBCDIC and ASCII) may have diferent encoding schemes. To write a program that can run on all diferent kind of computers and get the same comparison results, one can only assume the following ordering sequences:
A < B < C < D < E < F < G < H < I < J < K < L < M < N < O < P < Q < R < S < T < U < V < W < X < Y < Z
a < b < c < d < e < f < g < h < i < j < k < l < m < n < o < p < q < r < s < t < u < v < w < x < y < z
0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9
If you compare characters in different sequences such as 'A' < 'a' and '2' >= 'N', you are asking for trouble since diferent encoding methods may produce diferent answers. Moreover, do not assume there exists a specifc order among upper and lower case letters, digits, and special symbols. Thus, '+' <= 'A', '*' >= '%', 'u' > '$', and '8' >= '?' make no sense. However, you can always compare if two characters are equal or not equal. Hence, '*' /= '9', 'a' == 'B' and '8' == 'b' are perfectly fne.
Here is the method for comparing two strings:
The comparison always starts at the frst character and proceeds from left to right.
If the two corresponding characters are equal, then proceed to the next pair of characters.
Otherwise, the string containing the smaller character is considered to be the smaller one. And, the comparison halts.
During the process comparison, if
o both strings have consumed all of their characters, they are equal since all of their corresponding characters are equal.
o otherwise, the shorter string is considered to be the smaller one.
Compare "abcdef" and "abcefg"
a b c d e f = = = < a b c e f g
The frst three characters of both strings are equal. Since 'd' of the frst string is smaller than 'e' of the second, "abcdef" < "abcefg" holds.
Compare "01357" and "013579"
0 1 3 5 7 = = = = = 0 1 3 5 7 9
Since all compared characters are equal and the frst string is shorter, "01357" < "013579" holds.
What is the result of "DOG" < "FOX"?
D O G < F O X
The frst character (i.e., 'D' < 'F') determines the outcome. That is, "DOG" < "FOX" yields .TRUE.
A S
PECIALN
OTEThe priority of all six relational operators is lower than the string concatenation operator //. Therefore, if a relational expression involves //, then all string concatenations must be carried out before evaluating the comparison operator. Here is an example:
"abcde" // "xyz" < "abc" // ("dex" // "ijk")
--> ["abcde" // "xyz"] < "abc" // ("dex" // "ijk") --> "abcdexyz" < "abc" // ("dex" // "ijk")
--> "abcdexyz" < "abc" // (["dex" // "ijk"]) --> "abcdexyz" < "abc" // ("dexijk")
--> "abcdexyz" < "abc" // "dexijk" --> "abcdexyz" < ["abc" // "dexijk"] --> "abcdexyz" < "abcdexijk"
--> .FALSE.
Fortran has five LOGICAL operators that can only be used with expressions whose results are
logical values (
i.e.
, .TRUE. or .FALSE.). All LOGICAL operators have priorities lower than
arithmetic and relational operators. Therefore, if an expression involving arithmetic, relational
and logical operators, the arithmetic operators are evaluated first, followed by the relational
operators, followed by the logical operators.
These five logical operators are
.NOT. : logical not .AND. : logical and .OR. : logical or
.EQV. : logical equivalence .NEQV. : logical not equivalence
The following is a table of these operators, including there priority and associativity.
Type Operator Associati vity
Arithme tic
** right to left
* / left to right + - left to right Relation
al
<< =
>> =
=
= /= none
Logical
.NOT. right to left
.AND. left to right .OR. left to right .EQV. .NEQV. left to right
T
RUTHT
ABLESThe evaluation of logical expressions is determined by truth tables. Let us start with the .NOT. operator.
.NO T.
Opera nd
E. .FALSE
.
.TRUE .
Note that .NOT. is a unary operator. Therefore, .NOT. a yields .TRUE. (
resp.
, .FALSE.) if the
value of LOGICAL variable a is .FALSE. (
resp.
, .TRUE.).
The following is the truth table of .AND.:
.AND. .TRU
Therefore, the result of logical expression a .AND. b is .TRUE. if and only if
both
operands a
and b are .TRUE.. In all other cases, the result is always .FALSE.
The following is the truth table of .OR.:
.OR. .TRU
Therefore, the result of logical expression a .OR. b is .FALSE. if and only if
both
operands a
and b are .FALSE.. In all other cases, the result is always .TRUE. In other words, if one of the
two operands of the .OR. operator is .TRUE., the result is .TRUE.
.EQV. .TRU
Therefore, the result of logical expression a .EQV. b is .TRUE. if and only if
both
operands a
and b have the same value (
i.e.
, both are .TRUE. or both are .FALSE.). As mentioned in
relational expressions, relational operators can only compare arithmetic values and cannot be
used to compare logical values. To compare if two logical values are equal, use .EQV.
The following is the truth table of .NEQV.:
.NEQ
Therefore, the result of logical expression a .NEQV. b is .TRUE. if and only if
both
operands a
and b do not have the same value. As mentioned in relational expressions, relational operators
can only compare arithmetic values and cannot be used to compare logical values. To compare if
two logical values are not equal, use .NEQV. Note that .NEQV is the opposite of .EQV.. Hence,
to test if logical variables x and y have different values, one can use .NOT. (x .EQV. y). Here, if
x and y have the same value, x .EQV. y is .TRUE. and .NOT. (x .EQV. y) is .FALSE. On the
other hand, if x and y have different values, x .EQV. y is .FALSE. and .NOT. (x .EQV. y) is
.TRUE.
P
RIORITYThe priority of .NOT. is the highest, followed by .AND., followed by .OR., followed by .EQV. and .NEQV. Note that .NOT. is right associative, while the other four are left associative.
Here are some examples:
.NOT. Something .AND. Another
--> .NOT. .TRUE. .AND. .FALSE. --> [.NOT. .TRUE.] .AND. .FALSE. --> .FALSE. .AND. .FALSE.
--> .FALSE.
In the above, since .NOT. has the highest priority, it is evaluated frst. Now, look at the following example:
.NOT. (Something .AND. Another)
--> .NOT. (.TRUE. .AND. .FALSE.) --> .NOT. ([.TRUE. .AND. .FALSE.]) --> .NOT. .FALSE.
--> .TRUE.
Let LOGICAL variables a, b and c have values .TRUE., .TRUE. and .FALSE., respectively.
Note that the above expression, if you like, can be rewritten with parentheses as follows:
(n**2 + 1 > 10) .AND. .NOT. (n < 3)
Let INTEGER variables m, n, x and y have values 3, 5, 4 and 2, respectively:
--> .NOT. ([.FALSE. .AND. .FALSE.]) .NEQV. (3 <= 5 .AND. 4 >= 2) --> .NOT. (.FALSE.) .NEQV. (3 <= 5 .AND. 4 >= 2)
--> [.NOT. .FALSE.] .NEQV. (3 <= 5 .AND. 4 >= 2) --> .TRUE. .NEQV. (3 <= 5 .AND. 4 >= 2)
--> .TRUE. .NEQV. ([3 <= 5] .AND. 4 >= 2) --> .TRUE. .NEQV. (.TRUE. .AND. 4 >= 2) --> .TRUE. .NEQV. (.TRUE. .AND. [4 >= 2]) --> .TRUE. .NEQV. (.TRUE. .AND. .TRUE.) --> .TRUE. .NEQV. ([.TRUE. .AND. .TRUE.]) --> .TRUE. .NEQV. (.TRUE.)
--> .TRUE. .NEQV. .TRUE. --> .FALSE.
A
SSIGNMENTSThe result of a logical expression can be assigned into a LOGICAL variable. Note that only logical values can be put into LOGICAL variables. The follow assignments save the results of the examples into LOGICAL variables:
LOGICAL :: Result1, Result2, Result3, Result4
Result1 = .NOT. Something .AND. Another Result2 = .NOT. a .OR. .NOT. b .AND. c
Result3 = (n**2 + 1 > 10) .AND. .NOT. (n < 3)
Result4 = .NOT. (m > n .AND. x < y) .NEQV. (m <= n .AND. x >= y)
Thus, Result1, Result2, Result3 and Results receive .FALSE., .FALSE., .TRUE. and .FALSE., respectively.
IF-THEN-ELSE-END IF
The most general form of the IF-THEN-ELSE-END IF statement is the following:
IF (logical-expression) THEN statements-1
ELSE
statements-2 END IF
where statements-1 and statements-2 are sequences of executable statements, and logical-expression is a logical logical-expression. The execution of this IF-THEN-ELSE-END IF statement goes as follows:
if the result is .TRUE., the statements in statements-1 are executed if the result is .FALSE., the statements in statements-2 are executed
after fnish executing statements in statements-1 or statements-2, the statement following END IF is executed.
E
XAMPLES The following code frst reads in an integer into INTEGER variable Number. Then, if Number can be divided evenly by 2 (i.e., Number is a multiple of 2), the
WRITE(*,*) between IF and ELSE is executed and shows that the number is even; otherwise, the WRITE(*,*) between ELSE and END IF is executed and shows that the number is odd. Function MOD(x,y) computes the remainder of x divided by y. This is the the remainder (or modulo) function
INTEGER :: Number
READ(*,*) Number
IF (MOD(Number, 2) == 0) THEN WRITE(*,*) Number, ' is even' ELSE
WRITE(*,*) Number, ' is odd' END IF
The following program segment computes the absolute value of X and saves the result into variable Absolute_X. Recall that the absolute value of x is x if x is non-negative; otherwise, the absolute value is -x. For example, the absolute value of 5 is 5 and the absolute value of -4 is 4=-(-4). Also note that the WRITE(*,*) statement has been intentionally broken into two lines with the continuation line symbol &.
REAL :: X, Absolute_X
X = ...
IF (X >= 0.0) THEN Absolute_X = X ELSE
Absolute_X = -X END IF
WRITE(*,*) 'The absolute value of ', x, & ' is ', Absolute_X
The following program segment reads in two integer values into a and b and fnds the smaller one into Smaller. Note that the WRITE(*,*) has also been broken into two lines.
INTEGER :: a, b, Smaller
READ(*,*) a, b IF (a <= b) THEN Smaller = a ELSE
Smaller = b END IF
A U
SEFULT
IPYou may fnd the following way of organizing IF-THEN-ELSE-END IF very useful, especially when your program logic is reasonably complex.
Draw a rectangular box and a vertical line dividing the box into two parts. Then, write down the
logical expression in the left part and draw a horizontal line dividing the right parts into two
smaller ones. The upper rectangle is filled with what you want to do when the logical expression
is .TRUE., while the lower rectangle is filled with what you want to do when the logical
expression is .FALSE.:
logical-expression
what you want to do when the logical expression is .TRUE.
what you want to do when the logical expression is .FALSE.
For example, the third example above has the following description:
a <= b
a is the smaller number
b is the smaller number
Although this is an easy example, you will sense its power when you will be dealing with more
complex problems.
IF-THEN-END IF
The IF-THEN-END IF form is a simplification of the general IF-THEN-ELSE-END IF form
with the ELSE part omitted:
IF (logical-expression) THEN statements
where statements is a sequence of executable statements, and logical-expression is a logical expression. The execution of this IF-THEN-ELSE-END IF statement goes as follows:
the logical-expression is evaluated, yielding a logical value
if the result is .TRUE., the statements in statements are executed, followed by the statement following the IF-THEN-END IF statement.
if the result is .FALSE., the statement following the IF-THEN-END IF is executed. In other words, if logical-expression is .FALSE., there is no action taken.
E
XAMPLES The following program segment computes the absolute value of X and saves the result into variable Absolute_X. Recall that the absolute value of x is x if x is non-negative; otherwise, the absolute value is -x. For example, the absolute value of 5 is 5 and the absolute value of -4 is 4=-(-4). Also note that the WRITE(*,*) statement has been intentionally broken into two lines with the continuation line symbol &. The trick is that the value of X is frst saved to Absolute_X whose value is changed later only if the value of X is less than zero.
REAL :: X, Absolute_X
X = ... Absolute_X = X IF (X < 0.0) THEN Absolute_X = -X END IF
WRITE(*,*) 'The absolute value of ', x, & ' is ', Absolute_X
The following program segment reads in two integer values into a and b and fnds the smaller one into Smaller. Note that the WRITE(*,*) has also been broken into two lines. This uses the same trick discussed in the previous example.
INTEGER :: a, b, Smaller
READ(*,*) a, b Smaller = a IF (a > b) THEN Smaller = b END IF
Write(*,*) 'The smaller of ', a, ' and ', & b, ' is ', Smaller
In many cases, it is required to do something when certain condition is satisfed; otherwise, do nothing. This is exactly what we need the form of IF-THEN-END IF. In the following, an INTEGER variable Counter is used for counting something. When its value is a multiple of 10, a blank line is displayed.
INTEGER :: Counter
IF (MOD(Counter, 10) == 0) THEN WRITE(*,*)
A U
SEFULT
IPThe box trick can also be used with this IF-THEN-END IF form. Since there is no ELSE, you can leave the lower part empty like the following:
logical-expression
what you want to do when the logical expression is .TRUE.
nothing is here!!!
L
OGICAL
IF
The logical IF is the simplest form. It has the following form:
IF (logical-expression) one-statement
where one-statement is a executable statement which is not another IF, and logical-expression is a logical logical-expression. The execution of this logical IF statement goes as follows:
the logical-expression is evaluated, yielding a logical value
if the result is .TRUE., the statement in one-statement is executed, followed by the statement following the logical IF statement.
if the result is .FALSE., the statement following the logical IF is executed. In other words, when logical-expression is .FALSE., there is no action taken.
Note that this logical IF does have its use although it looks not so powerful comparing with
IF-THEN-ELSE-END IF and IF-THEN-END IF.
E
XAMPLES The following program segment computes the absolute value of X and saves the result into variable Absolute_X. Recall that the absolute value of x is x if x is non-negative; otherwise, the absolute value is -x. For example, the absolute value of 5 is 5 and the absolute value of -4 is 4=-(-4). Also note that the WRITE(*,*) statement has been intentionally broken into two lines with the continuation line symbol &. The trick is that the value of X is frst saved to Absolute_X whose value is changed later only if the value of X is less than zero.
REAL :: X, Absolute_X
X = ... Absolute_X = X
IF (X < 0.0) Absolute_X = -X
The following program segment reads in two integer values into a and b and fnds the smaller one into Smaller. Note that the WRITE(*,*) has also been broken into two lines. This uses the same trick discussed in the previous example.
INTEGER :: a, b, Smaller
READ(*,*) a, b Smaller = a
IF (a > b) Smaller = b
Write(*,*) 'The smaller of ', a, ' and ', & b, ' is ', Smaller
In many cases, it is required to do something when certain condition is satisfed; otherwise, do nothing. This is exactly what we need the form of IF-THEN-END IF. In the following, an INTEGER variable Counter is used for counting something. When its value is a multiple of 10, a blank line is displayed.
INTEGER :: Counter
IF (MOD(Counter, 10) == 0) WRITE(*,*)
The following is wrong since the one-statement if a logical IF can not be another IF statement.
INTEGER :: a, b, c
IF (a < b) IF (b < c) WRITE(*,*) a, b, c
From the above examples, one can easily see that if the THEN part has exactly one statement and there is no ELSE, the logical IF statement can save some space making a program a little shorter. But, my advice is that don't use it whenever it is possible.
PROGRAMMING EXAMPLE 1: QUADRATIC EQUATION SOLVER
P
ROBLEMS
TATEMENTGiven a quadratic equation as follows:
Write a program to read in the coefficients a, b and c, and compute and display the roots. If the
discriminant b*b - 4*a*c is negative, the equation has complex root. Thus, this program should
solve the equation if the discriminant is non-negative and show a message otherwise.
S
OLUTION! ---! Solve Ax^2 + Bx + C = 0 given B*B-4*A*C >= 0 ! Now, we are able to detect complex roots.
!
---PROGRAM QuadraticEquation IMPLICIT NONE
REAL :: a, b, c REAL :: d
REAL :: root1, root2
! read in the coefficients a, b and c
READ(*,*) a, b, c WRITE(*,*) 'a = ', a WRITE(*,*) 'b = ', b WRITE(*,*) 'c = ', c WRITE(*,*)
! compute the square root of discriminant d
d = b*b - 4.0*a*c
IF (d >= 0.0) THEN ! is it solvable? d = SQRT(d)
root1 = (-b + d)/(2.0*a) ! first root root2 = (-b - d)/(2.0*a) ! second root WRITE(*,*) 'Roots are ', root1, ' and ', root2 ELSE ! complex roots WRITE(*,*) 'There is no real roots!'
WRITE(*,*) 'Discriminant = ', d END IF
END PROGRAM QuadraticEquation
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUT If the input to the program consists of 1.0, 5.0 and 2.0, we have the following output. Since the discriminant is b*b - 4.0*a*c = 5.0*5.0 - 4.0*1.0*2.0 = 17.0 > 0.0, the THEN part is executed and the real roots are -0.438447237 and -4.561553.
1.0 5.0 2.0
c = 2.
Roots are -0.438447237 and -4.561553
If the input to the program consists of 1.0, 2.0 and 5.0, we have the following output. Since the discriminant is b*b - 4.0*a*c = 2.0*2.0 - 4.0*1.0*5.0 = -16.0 < 0.0, the ELSE part is executed and a message of no real roots is displayed followed the value of the discriminant.
1.0 2.0 5.0
a = 1. b = 2. c = 5.
There is no real roots! Discriminant = -16.
D
ISCUSSIONHere is the box trick of this program. Note that information in diferent parts of the box do not have to be very precise. As long as it can tell what to do, it would be sufcient.
b*b - 4.0*a*c >= 0.0
computes the real roots
there is no real roots
PROGRAMMING EXAMPLE 2: FINAL MARK COMPUTATION
P
ROBLEMS
TATEMENTTwo examination papers are written at the end of the course. The final mark is either the average
of the two papers, or the average of the two papers and the class record mark (all weighted
equally), whichever is the higher. The program should reads in the class record mark and the
marks of the papers, computes the average, and shows PASS (>= 50%) or FAIL (< 50%).
S
OLUTION! FAIL (< 50%).
!
---PROGRAM FinalMark IMPLICIT NONE
REAL :: Mark1, Mark2 ! the marks of the papers REAL :: Final ! the final marks
REAL :: ClassRecordMark ! the class record mark
REAL, PARAMETER :: PassLevel = 50.0 ! the pass level
READ(*,*) ClassRecordMark, Mark1, Mark2
Final = (Mark1 + Mark2) / 2.0 IF (Final <= ClassRecordMark) THEN
Final = (Mark1 + Mark2 + ClassRecordMark) / 3.0 END IF
WRITE(*,*) 'Class Record Mark : ', ClassRecordMark WRITE(*,*) 'Mark 1 : ', Mark1
WRITE(*,*) 'Mark 2 : ', Mark2 WRITE(*,*) 'Final Mark : ', Final
IF (Final >= PassLevel) THEN
WRITE(*,*) 'Pass Status : PASS' ELSE
WRITE(*,*) 'Pass Status : FAIL' END IF
END PROGRAM FinalMark
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUT If the input to class record mark, the mark of the frst paper, and the mark of the second paper are 40.0, 60.0 and 43.0, the average is (60.0 + 43.0)/2 = 51.5, which is larger than the class record mark (40.0). Therefore, this student has a fnal mark 51.5 and receives a PASS status.
40.0 60.0 43.0
Class Record Mark : 40. Mark 1 : 60. Mark 2 : 43. Final Mark : 51.5 Pass Status : PASS
If the input to class record mark, the mark of the frst paper, and the mark of the second paper are 60.0, 45.0 and 43.0, then the average is (45.0 + 43.0)/2 = 44.0, which is less than the class record mark (60.0). Therefore, this student's new mark is the average of his marks and the class record mark, (60.0 + 45.0 + 43.0)/3.0 = 49.33333. Since this new mark is less than 50.0, this student receives a FAIL status.
Class Record Mark : 60. Mark 1 : 45. Mark 2 : 43.
Final Mark : 49.3333321 Pass Status : FAIL
D
ISCUSSION The READ statement reads in values for ClassRecordMark, Mark1 and Mark2. The average of papers is computed and stored in Final
If this fnal mark is less than or equal to the class record mark, a new fnal mark is computed as the average of the two marks and the class record mark. Here, the IF-THEN-END form is used. You can use the logical IF form; but, this line could be too long. As mentioned earlier, the IF-THEN-END IF is preferred.
The four WRITE(*,*) statements display the input and the computed fnal mark. Finally, the IF-THEN-ELSE-END IF determines if the fnal mark is a pass or a fail.
P
ROGRAMMING
E
XAMPLE
3: H
ERON
'
S
F
ORMULA
FOR
C
OMPUTING
T
RIANGLE
A
REA
P
ROBLEMS
TATEMENTGiven a triangle with side lengths a, b and c, its area can be computed using the Heron's formula:
where s is the half of the perimeter length:
Write a program to read in the coefficients a, b and c, and compute the area of the triangle.
However, not any three numbers can make a triangle. There are two conditions. First, all side
lengths must be positive:
In the program, these two conditions must be checked before computing the triangle area;
otherwise, square root computation will be in trouble.
S
OLUTION! ---! Compute the area of a triangle using Heron's formula !
---PROGRAM HeronFormula IMPLICIT NONE
REAL :: a, b, c ! three sides
REAL :: s ! half of perimeter REAL :: Area ! triangle area
LOGICAL :: Cond_1, Cond_2 ! two logical conditions
READ(*,*) a, b, c
WRITE(*,*) "a = ", a WRITE(*,*) "b = ", b WRITE(*,*) "c = ", c WRITE(*,*)
Cond_1 = (a > 0.) .AND. (b > 0.) .AND. (c > 0.0) Cond_2 = (a+b > c) .AND. (a+c > b) .AND. (b+c > a) IF (Cond_1 .AND. Cond_2) THEN
s = (a + b + c) / 2.0
Area = SQRT(s*(s-a)*(s-b)*(s-c)) WRITE(*,*) "Triangle area = ", Area ELSE
WRITE(*,*) "ERROR: this is not a triangle!" END IF
END PROGRAM HeronFormula
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUT If the input to the program consists of 3.0, 5.0 and 7.0, we have the following output. Since the value of all input are positive and the sum of any two is larger than the third (i.e., 3.0+5.0 > 7.0, 3.0+7.0+5.0 and 5.0+7.0>3.0), both conditions hold and the program can compute the area of the triangle. The area is 6.49519062.
3.0 5.0 7.0
Triangle area = 6.49519062
If the input to the program consists of 3.0, 4.0 and 7.0, we have the following output. Although all input values are positive, this is not a triangle since the sum of the frst side (3.0) and the second (4.0) is not grater than the third (8.0). The program generates an error message.
3.0 4.0 8.0
a = 3. b = 4. c = 8.
ERROR: this is not a triangle!
If the input to the program consists of -1.0, 3.0 and 5.0, we have the following output. Since not all input values are positive, this is not a triangle.
-1.0 3.0 5.0
a = -1. b = 3. c = 5.
ERROR: this is not a triangle!
D
ISCUSSION This program uses two LOGICAL variables, Cond_1 and Cond_2 to store the results of the two conditions.
The conditions are checked with the frst two assignments.
Since all side lengths must be greater than zero, operator .AND. are used to connect a > 0.0, b > 0.0 and c > 0.0.
Since the sum of any two side lengths must be greater than the third side length, all three comparisons must be .TRUE. and operator .AND. is used.
Since both conditions must be true in order to have a triangle, .AND. is also used in the IF-THEN-ELSE-END IF statement.
If both conditions are .TRUE., the THEN part is executed, where the value of s and the area is computed and displayed.
If one or both conditions is .FALSE., the input is not a triangle and an error message is displayed.
You can pull all six comparisons into a single logical expression. But, this expression could be too long to be ft into a single line. While continuation line can be used, it may not be readable. So, I prefer to have separate lines.
Here is the box trick of this program.
a, b and c form a triangle
displays an error message
NESTED IF-THEN-ELSE-END IF
The THEN part and the ELSE part, if any, can contain one or more IF-THEN-ELSE-END IF
statement in one of the three forms. That is, when you feel it is necessary, you can use as many
IF-THEN-ELSE-END IF statements in the THEN part and the ELSE part as you want.
However, please note that any such IF-THEN-ELSE-END IF must be fully contained in the
THEN part or the ELSE part. If you follow the box trick, this requirement is automatically
satisfied. The following is an example:
IF (logical-expression) THEN statements
IF (logical-expression) THEN statements
ELSE
statements END IF
statements ELSE
statements
IF (logical-expression) THEN statements
END IF statements END IF
E
XAMPLES Suppose we need a program segment to read a number x and display its sign. More precisely, if x is positive, a + is displayed; if x is negative, a - is displayed; otherwise, a 0 is displayed. With an IF-THEN-ELSE-END IF statement, we have a two-way decision (i.e., true or false). What we need is a tree-way decision and some trick is required. In this case, the box trick can be very helpful.
Let us start testing if x is positive. What we get is the following:
x > 0
display +
In the lower part, no decision can been reached. What we want to know is finding out is x
is zero or negative (x cannot be positive here since it has been ruled out in the upper
part). To determine whether a - or a 0 should be displayed, one more decision is required:
x < 0
display
-display 0)
Since this is the work for the lower rectangle, let us put it there yielding the following:
x > 0
display +
x < 0
display - display 0
Converting to a IF-THEN-ELSE-END IF construct is easy since the above box is
almost identical to that. So, here is our answer:
IF (x > 0) THEN WRITE(*,*) '+' ELSE
IF (x < 0) THEN WRITE(*,*) '-' ELSE
WRITE(*,*) '0' END IF
END IF
Given a x, we want to display the value of -x if x < 0, the value of x*x if x is in the range of 0 and 1 inclusive, and the value of 2*x if x is greater than 1.
Obviously, this problem cannot be solved with a two-way IF and the box trick becomes
useful. Let us start with x<0.
x < 0
display -x
here we have x >= 0
x <= 1
x is in the range of 0 and 1. display x*x
here we have x > 1. display 2*x
Inserting this box into the previous one yields the following final result:
x < 0
display -x
x <= 1
display x*x display 2*x
Converting to using IF, we have the following:
IF (x < 0) THEN WRITE(*,*) -x ELSE
IF (x <= 1) THEN WRITE(*,*) x*x ELSE
WRITE(*,*) 2*x END IF
END IF
Given three numbers a, b and c, we want to fnd out the smallest one.
There are many solutions to this problem; but, we shall use the box trick again. Let us
pick two numbers, say a and b. Thus, we get the following:
a < b
a has the potential to be the smallest since b <= a, b has the potential to be the smallest
Now we know a possible smallest number. To find the real smallest one, this "possible"
number must be compared against c. If the possible one is a (the upper part), we need to
do the following:
a < c
a is the smallest
the smallest
Let us turn to the lower part, where b has the potential to be the smallest. Comparing with
c yields:
b < c
b is the smallest
since c <= b and b <= a, c is the smallest
Inserting the above two boxes into the first one yields the following complete solution:
a < b
a < c
the smallest is a
the smallest is c
b < c
the smallest is b
the smallest is c
Converting to the IF version, we have
IF (a < b) THEN IF (a < c) THEN Result = a ELSE
Result = c END IF
ELSE
IF (b < c) THEN Result = b ELSE
Result = c END IF
END IF
WRITE(*,*) 'The smallest is ', Result
The above code segment uses variable Result to hold the smallest value.
The Nested IF-THEN-ELSE-END IF statement could produce a deeply nested IF statement
which is difficult to read. There is a short hand to overcome this problem. It is the
IF-THEN-ELSE IF-END-IF version. Its syntax is shown below:
IF (logical-expression-1) THEN statements-1
ELSE IF (logical-expression-2) THEN statements-2
ELSE IF (logical-expression-3) THEN statement-3
ELSE IF (...) THEN ...
ELSE
statements-ELSE END IF
Fortran evaluates logical-expression-1 and if the result is .TRUE., statements-1 is executed followed by the statement after END IF. If logical-expression-1 is .FALSE., Fortran evaluates logical-expression-2 and executes statements-2 and so on. In general, if logical-expression-n is .TRUE., statements-n is executed followed by the statement after END IF; otherwise, Fortran continues to evaluate the next logical expression.
If all logical expressions are .FALSE. and if ELSE is there, Fortran executes the
statements-ELSE
; otherwise, Fortran executes the statement after the END IF.
Note that the statements in the THEN section, ELSE IF section, and ELSE section can be
another IF statement.
E
XAMPLES Suppose we need a program segment to read a number x and display its sign. More precisely, if x is positive, a + is displayed; if x is negative, a - is displayed; otherwise, a 0 is displayed. Here is a possible solution using IF-THEN-ELSE IF-END IF:
IF (x > 0) THEN WRITE(*,*) '+' ELSE IF (x == 0) THEN WRITE(*,*) '0' ELSE
WRITE(*,*) '-' END IF
Given a x, we want to display the value of -x if x < 0, the value of x*x if x is in the range of 0 and 1 inclusive, and the value of 2*x if x is greater than 1.
The following is a possible solution:
IF (x < 0) THEN WRITE(*,*) -x ELSE IF (x <= 1) THEN WRITE(*,*) x*x ELSE
END IF
Consider the following code segment:
INTEGER :: x CHARACTER(LEN=1) :: Grade
IF (x < 50) THEN Grade = 'F'
ELSE IF (x < 60) THEN Grade = 'D'
ELSE IF (x < 70) THEN Grade = 'C'
ELSE IF (x < 80) THEN Grade = 'B'
ELSE
Grade = 'A' END IF
First, if x is less than 50, 'F' is assigned to Grade. If x is greater than or equal to 50, the execution continue with the frst ELSE IF where x < 60 is tested. If it is .TRUE., 'D' is assigned to Grade. Note that one can reach the test of x < 60 simply because the test x < 50 is .FALSE.. Therefore, when reaches x < 60, we are sure that x >= 50 must hold and as a result, Grade receives 'D' if x is greater than or equal to 50 and is less than 60.
By the same token, we know that if x is greater than or equal to 60 and is less than 70,
Grade receives 'C'. If x is greater than or equal to 70 and is less than 80, Grade receives
'B'. Finally, if x is greater than or equal to 80, Grade receives 'A'.
The frst and second examples show that IF-THEN-ELSE IF-END IF can save some space and at the same time make a program more readable. Compare these two solutions with those using nest IF.
Note also that not all nested IF can be converted to the IF-THEN-ELSE IF-ELSE-END-IF
form. For example, the example of determining the smallest of three numbers cannot be
converted immediately. In general, if all tests (
i.e.
, logical expressions) are mutually exclusive,
then the chance to have a successful conversion is high. Otherwise, rewriting some parts or
combining logical expression can be helpful. Here is one more example:
Let us reconsider the problem of finding the smallest of three given numbers. We know that if a
is the smallest, then it must be smaller than the other two. Moreover, the condition for a number
being the smallest is mutually exclusive. Thus, we have a successful conversion as follows:
IF (a < b .AND. a < c) THEN Result = a
ELSE IF (b < a .AND. b < c) THEN Result = b
ELSE
Q
UADRATIC
E
QUATION
S
OLVER
- A
GAIN
P
ROBLEMS
TATEMENTGiven a quadratic equation as follows:
if b*b-4*a*c is non-negative, the roots of the equation can be solved with the following
formulae:
Write a program to read in the coefficients a, b and c, and solve the equation. Note that a
quadratic equation has repeated root if b*b-4.0*a*c is equal to zero. This program should
distinguish repeated roots from distinct roots.
S
OLUTION! ---! Solve Ax^2 + Bx + C = 0 given B*B-4*A*C >= 0 ! Now, we are able to detect complex roots and ! repeated roots.
!
---PROGRAM QuadraticEquation IMPLICIT NONE
REAL :: a, b, c REAL :: d
REAL :: root1, root2
! read in the coefficients a, b and c
READ(*,*) a, b, c WRITE(*,*) 'a = ', a WRITE(*,*) 'b = ', b WRITE(*,*) 'c = ', c WRITE(*,*)
d = b*b - 4.0*a*c
IF (d > 0.0) THEN ! distinct roots? d = SQRT(d)
root1 = (-b + d)/(2.0*a) ! first root root2 = (-b - d)/(2.0*a) ! second root WRITE(*,*) 'Roots are ', root1, ' and ', root2 ELSE
IF (d == 0.0) THEN ! repeated roots? WRITE(*,*) 'The repeated root is ', -b/(2.0*a) ELSE ! complex roots
WRITE(*,*) 'There is no real roots!' WRITE(*,*) 'Discriminant = ', d END IF
END IF
END PROGRAM QuadraticEquation
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUT If the input to the program consists of 1.0, 5.0 and 2.0, we have the following output. Since the discriminant is b*b - 4.0*a*c = 5.0*5.0 - 4.0*1.0*2.0 = 17.0 > 0.0, the THEN part is executed and the real roots are -0.438447237 and -4.561553.
1.0 5.0 2.0
a = 1. b = 5. c = 2.
Roots are -0.438447237 and -4.561553
If the input to the program consists of 1.0, -10.0 and 25.0, we have the following output. Since the discriminant is b*b - 4.0*a*c = (-10.0)*(-10.0) - 4.0*1.0*25.0 = 0.0, the ELSE part is executed. Since there is a nested IF-THEN-ELSE-END IF in the ELSE, d = 0.0 is tested and therefore yields a repeated root 5.
1.0 -10.0 25.0
a = 1. b = -10. c = 25.
The repeated root is 5.
If the input to the program consists of 1.0, 2.0 and 5.0, we have the following output. Since the discriminant is b*b - 4.0*a*c = 2.0*2.0 - 4.0*1.0*5.0 = -16.0 < 0.0, the ELSE part is executed. Since d < 0.0, the ELSE part of the inner IF-THEN-ELSE-END IF is executed and a message of no real roots is displayed followed by the value of the discriminant.
1.0 2.0 5.0
c = 5.
There is no real roots! Discriminant = -16.
D
ISCUSSIONHere is the box trick of this program.
b*b - 4.0*a*c > 0.0
computes the real roots
repeated root or no real root
The lower part is not complete yet since we do not know if the equation has a repeated root.
Therefore, one more test is required:
b*b - 4.0*a*c = 0.0
computes the repeated root
no real root
Inserting this back to the original yields the following final result:
b*b - 4.0*a*c > 0.0
computes the real roots
b*b - 4.0*a*c = 0.0
compute the repeated root
no real root
This is the logic used in the above program.
The following is an equivalent program that uses ELSE-IF construct rather than nested IF:
! ---! Solve Ax^2 + Bx + C = 0 given B*B-4*A*C >= 0 ! Now, we are able to detect complex roots and ! repeated roots.
!
REAL :: a, b, c REAL :: d
REAL :: root1, root2
! read in the coefficients a, b and c
READ(*,*) a, b, c WRITE(*,*) 'a = ', a WRITE(*,*) 'b = ', b WRITE(*,*) 'c = ', c WRITE(*,*)
! compute the discriminant d
d = b*b - 4.0*a*c
IF (d > 0.0) THEN ! distinct roots? d = SQRT(d)
root1 = (-b + d)/(2.0*a) ! first root root2 = (-b - d)/(2.0*a) ! second root WRITE(*,*) 'Roots are ', root1, ' and ', root2 ELSE IF (d == 0.0) THEN ! repeated roots? WRITE(*,*) 'The repeated root is ', -b/(2.0*a) ELSE ! complex roots WRITE(*,*) 'There is no real roots!'
WRITE(*,*) 'Discriminant = ', d END IF
END PROGRAM QuadraticEquation
Click here to download this program.
Its logic is shown below using the box trick.
b*b - 4.0*a*c ? 0.0
>computes the real roots
=computes the repeated root
>
no real root
P
ROBLEMS
TATEMENTGiven a quadratic equation as follows:
if b*b-4*a*c is non-negative, the roots of the equation can be solved with the following
formulae:
Write a program to read in the coefficients a, b and c, and solve the equation. Note that a
quadratic equation has repeated root if b*b-4.0*a*c is equal to zero.
However, if a is zero, the equation becomes a linear one whose only solution is -c/b if b is not
zero. Otherwise, if b is zero, two cases are possible. First, if c is also zero, any number can be a
solution because all three coefficients are zero. Otherwise, the equation c = 0 cannot have any
solution.
This program should handle
all
cases.
S
OLUTION! ---! Solve Ax^2 + Bx + C = 0 given B*B-4*A*C >= 0 ! Now, we are able to detect the following: ! (1) unsolvable equation
! (2) linear equation ! (3) quadratic equation ! (a) distinct real roots ! (b) repeated root
! (c) no real roots
!
---PROGRAM QuadraticEquation IMPLICIT NONE
REAL :: a, b, c REAL :: d
REAL :: root1, root2
! read in the coefficients a, b and c
WRITE(*,*) 'a = ', a WRITE(*,*) 'b = ', b WRITE(*,*) 'c = ', c WRITE(*,*)
IF (a == 0.0) THEN ! could be a linear equation IF (b == 0.0) THEN ! the input becomes c = 0 IF (c == 0.0) THEN ! all numbers are roots WRITE(*,*) 'All numbers are roots'
ELSE ! unsolvable WRITE(*,*) 'Unsolvable equation' END IF
ELSE ! linear equation
WRITE(*,*) 'This is linear equation, root = ', -c/b END IF
ELSE ! ok, we have a quadratic equation d = b*b - 4.0*a*c
IF (d > 0.0) THEN ! distinct roots? d = SQRT(d)
root1 = (-b + d)/(2.0*a) ! first root root2 = (-b - d)/(2.0*a) ! second root
WRITE(*,*) 'Roots are ', root1, ' and ', root2 ELSE IF (d == 0.0) THEN ! repeated roots? WRITE(*,*) 'The repeated root is ', -b/(2.0*a) ELSE ! complex roots
WRITE(*,*) 'There is no real roots!' WRITE(*,*) 'Discriminant = ', d END IF
END IF
END PROGRAM QuadraticEquation
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUTSince we have been doing the quadratic part in several similar examples, the following concentrates on the order part of the program.
If the input to the program consists of 0.0, 1.0 and 5.0, we have the following output. Since a is zero, this could be a linear equation. Since b=1.0, it is a linear equation 1.0*x + 5.0 = 0.0 with the only root -5.0/2.0=-5.0.
0.0 1.0 5.0
a = 0.E+0 b = 1. c = 5.
This is linear equation, root = -5.
If the input to the program consists of 0.0, 0.0 and 0.0, we have the following output. Since all coefcients are zero, any number is a root.
a = 0.E+0 b = 0.E+0 c = 0.E+0
All numbers are roots
If the input to the program consists of 0.0, 0.0 and 4.0, we have the following output. Since the equation becomes 4.0 = 0.0, which is impossible. Therefore, this is not a solvable equation.
0.0 0.0 4.0
a = 0.E+0 b = 0.E+0 c = 4.
Unsolvable equation
D
ISCUSSIONHere is the box trick of this program. It is more complex than all previous versions of quadratic equation solvers.
Let us start with linear equations.
a = 0
it could be a linear equation
a quadratic equation
Since we have learned to do the quadratic part, we shall do the linear equation part first. To be a
linear equation, b cannot be zero and this has to be addressed in the upper rectangle:
a = 0
b = 0
need to know if c is zero
the equation is linear b*x+c=0
a quadratic equation
If c is zero, then every number is a root and we have:
a = 0
b = 0 c =
0
every number is a root
this equation is not solvable
b*x+c=0 a quadratic equation
To complete the bottom rectangle, let us take the box from previous example. The final result is:
a = 0
b = 0
c = 0
every number is a root
this equation is not solvable
the equation is linear b*x+c=0
b*b -4.0*a*c ? 0.0
> computes the real roots
= computes the repeated root
> no real root
The above program is written based on this logic.
S
ORT
T
HREE
N
UMBERS
P
ROBLEMS
TATEMENTGive three integers, display them in ascending order. For example, if the input is 2, 3 and 1, this
program should display 1, 2 and 3.
S
OLUTION! ---! This program reads in three INTEGERs and displays them ! in ascending order.
!
---PROGRAM Order IMPLICIT NONE
READ(*,*) a, b, c
IF (a < b) THEN ! a < b here
IF (a < c) THEN ! a < c : a the smallest IF (b < c) THEN ! b < c : a < b < c WRITE(*,*) a, b, c
ELSE ! c <= b : a < c <= b WRITE(*,*) a, c, b
END IF
ELSE ! a >= c : c <= a < b WRITE(*,*) c, a, b
END IF
ELSE ! b <= a here
IF (b < c) THEN ! b < c : b the smallest IF (a < c) THEN ! a < c : b <= a < c WRITE(*,*) b, a, c
ELSE ! a >= c : b < c <= a WRITE(*,*) b, c, a
END IF
ELSE ! c <= b : c <= b <= a WRITE(*,*) c, b, a
END IF END IF
END PROGRAM Order
Click here to download this program.
D
ISCUSSIONThis is a good example for using the box trick. The main idea is that if we know the smallest number, then one comparison between the remaining two would give the second smallest and the largest number. Finding the smallest of three numbers has been discussed in
nested IF .
So, let us start with a:
a < b
a may be the smallest
b may be the smallest
For the upper rectangle, we need to know if a is less than c, while for the lower rectangle we
need to know if b is less than c:
a < b
a < c
c <= a < b here, sorted!!!
b < c
b is the smallest, relation between a and c unknown
c <= b <= a here, sorted!!!
For the top rectangle, we need one more comparison b < c and for the rectangle on the third row
we need a < c. The following is our final result:
a < Here is the box diagram:
< b b here
c < b <= a here
Converting this diagram to IF-THEN-ELSE IF we have the following:
! ---! This program reads in three INTEGERs and displays them ! in ascending order.
!
---PROGRAM Order IMPLICIT NONE
INTEGER :: a, b, c
READ(*,*) a, b, c
IF (a <= b .AND. a <= c) THEN ! a the smallest IF (b <= c) THEN ! a <= b <= c WRITE(*,*) a, b, c
ELSE ! a <= c <= b WRITE(*,*) a, c, b
END IF
ELSE IF (b <= a .AND. b <= c) THEN ! b the smallest IF (a <= c) THEN ! b <= a <= c WRITE(*,*) b, a, c
ELSE ! b <= c <= a WRITE(*,*) b, c, a
END IF
ELSE ! c the smallest IF (a <= b) THEN ! c <= a <= b WRITE(*,*) c, a, b
ELSE ! c <= b <= a WRITE(*,*) c, b, a
END IF END IF
END PROGRAM Order
Click here to download this program.
SELECT CASE STATEMENT
SELECT CASE (selector) CASE (label-list-1) statements-1 CASE (label-list-2) statements-2 CASE (label-list-3) statements-3 ... CASE (label-list-n) statements-n CASE DEFAULT
statements-DEFAULT END SELECT
where statements-1, statements-2, statements-3, ..., statements-n and statements-DEFAULT are sequences of executable statements, including the SELECT CASE statement itself, and selector is an expression whose result is of type INTEGER, CHARACTER or LOGICAL (i.e., no REAL type can be used for the selector). The label lists 1, 2, label-list-3, ..., and label-list-n are called case labels.
A label-list is a list of labels, separated by commas. Each label must be one of the following
forms. In fact, three of these four are identical to an
extent specifier
for substrings:
value
value-1 : value-2 value-1 :
: value-2
where value, value-1 and value-2 are constants or alias defned by PARAMETER. The type of these constants must be identical to that of the selector.
The frst form has only one value
The second form means all values in the range of value-1 and value-2. In this form, value-1 must be less than value-2.
The third form means all values that are greater than or equal to value-1
The fourth form means all values that are less than or equal to value-2
The rule of executing the SELECT CASE statement goes as follows: The selector expression is evaluated
If the result is in label-list-i, then the sequence of statements in statements-i are executed, followed by the statement following END SELECT
If the result is not in any one of the label lists, there are two possibilities:
o if CASE DEFAULT is there, then the sequence of statements in statements-DEFAULT are executed, followed by the statement following END SELECT
o if there is no CASE DEFAULT is not there, the statement following END SELECT is executed.
CASE DEFAULT is optional. But with a CASE DEFAULT, you are guaranteed that whatever the selector value, one of the labels will be used. I strongly suggest to add a CASE DEFAULT in every SELECT CASE statement.
The place for CASE DEFAULT can be anywhere within a SELECT CASE statement; however, put it at the end would be more natural.
E
XAMPLES The following uses Class to execute a selection. If Class is 1, Freshman is
displayed; if Class is 2, Sophomore is displayed; if Class is 3, Junior is displayed; if
Class is 4, Senior is displayed; and if Class is none of the above, Hmmmm, I don't know is displayed. After displaying one of the above, Done is displayed.
INTEGER :: Class
In the following, the value of CHARACTER variable Title is used as a selector. If its value is "DrMD" (resp., "PhD", "MS" and "BS"), then INTEGER variables DrMD
The follow example does not use CASE DEFAULT since the label lists have already covered all possibilities. If the value of Number is less than or equal to -1 (:-1), -1 is stored into Sign. If the value of Number is zero, 0 is stored into Sign. If the value of
Number is greater than or equal to 1, 1 is stored into Sign.
SELECT CASE (Number)
characters, which may not be letters' is displayed. In the last case, the value of c
could be one of these lower case letters not listed, an upper case letters, a digit, an operator, or any other character. So, if you only want to handle lower case letters, this program is incorrect.
CHARACTER(LEN=1) :: c
The following program uses the value of Number to determine the value of Range.
INTEGER :: Number, Range
Here is the result:
e
<= -10 1 CASE ( : -10, 10 : )
-9, -8, -7,
-6 6 CASE DEFAULT
-5, -4, -3 2 CASE (-5:-3, 6:9)
-2, -1, 0,
1, 2 3 CASE (-2:2)
3 4 CASE (3, 5)
4 5 CASE (4)
5 4 CASE (3, 5)
6, 7, 8, 9 2 CASE (-5:-3, 6:9)
>= 10 1 CASE ( : -10, 10 : )
P
ROGRAMMING
E
XAMPLE
1: L
ETTER
G
RADE
C
OMPUTATION
P
ROBLEMS
TATEMENTAt the end of a quarter, the average of three marks must be computed. Then, this average is
rounded and used to determine the corresponding letter grade. The letter grades are computed as
follows:
Range Grad e >= 90 A
< 90 and
>= 85 AB
>= 80
< 80 and
>= 75 BC
< 75 and >= 70 C
< 70 and
>= 65 CD
< 65 and >= 60 D
< 60 F
Write a program to read three marks, compute its average, round the average and use it to
determine the corresponding letter grade.
S
OLUTION! ---! This program reads three marks, computes their average ! and determines the corresponding letter grade with ! the following table:
!
! A : average >= 90 ! AB : 85 <= average < 90 ! B : 80 <= average < 84 ! BC : 75 <= average < 79 ! C : 70 <= average < 74 ! CD : 65 <= average < 69 ! D : 60 <= average < 64 ! F : average < 60
!
! where 'average' is the rounded average of the three ! marks. More precisely, if the average is 78.6, then it ! becomes 79 after rounding; or, if the average is 78.4, ! it becomes 78 after truncating.
!
---PROGRAM LetterGrade IMPLICIT NONE
REAL :: Mark1, Mark2, Mark3 REAL :: Average
CHARACTER(LEN=2) :: Grade
READ(*,*) Mark1, Mark2, Mark3
SELECT CASE (NINT(Average)) ! round Average before use CASE (:59) ! <= 59 ---> F Grade = 'F '
CASE (60:64) ! >= 60 and <= 64 ---> D Grade = 'D '
CASE (65:69) ! >= 65 and <= 69 ---> CD Grade = 'CD'
CASE (70:74) ! >= 70 and <= 74 ---> C Grade = 'C '
CASE (75:79) ! >= 75 and <= 79 ---> BC Grade = 'BC'
CASE (80:84) ! >= 80 and <= 84 ---> B Grade = 'B '
CASE (85:89) ! >= 84 and <= 89 ---> AB Grade = 'AB'
CASE DEFAULT ! >= 90 ---> A Grade = 'A '
END SELECT
WRITE(*,*) 'First Mark : ', Mark1 WRITE(*,*) 'Second Mark : ', Mark2 WRITE(*,*) 'Third Mark : ', Mark3 WRITE(*,*) 'Average : ', Average WRITE(*,*) 'Letter Grade : ', Grade
END PROGRAM LetterGrade
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUT The following output is generated from input 97.0, 90.0 and 94.0. The average is 93.66666641. The result after rounding is 94 and hence the letter grade is an A.
97.0 90.0 94.0
First Mark : 97. Second Mark : 90. Third Mark : 94.
Average : 93.6666641 Letter Grade : A
The following output is generated from input 92.0, 85.0 and 83.0. The average is 86.6666641. The result after rounding is 87 and hence the letter grade is an AB.
92.0 85.0 83.0
First Mark : 92. Second Mark : 85. Third Mark : 83.
Average : 86.6666641 Letter Grade : AB
75.0 60.0 45.0
First Mark : 75. Second Mark : 60. Third Mark : 45. Average : 60. Letter Grade : D
D
ISCUSSIONThis is an easy example and only one place requires further explanation. The concept of rounding is converting a real number to its nearest integer. Therefore, after rounding, 4.5 and 4.4 become 5 and 4, respectively. Moreover, after rounding, -4.5 and -4.4 become -5 and -4, respectively. The Fortran intrinsic function for rounding is NINT(), which was discussed in Fortran intrinsic functions.
P
ROGRAMMING
E
XAMPLE
2: C
HARACTER
T
ESTING
P
ROBLEMS
TATEMENTThis is an extension of an example discussed in SELECT CASE statement. This program reads
in a character and determines if it is a vowel, a consonant, a digit, one of the four arithmetic
operators, a space, or something else (
i.e.
, %, $, @, etc).
S
OLUTION! ---! This program reads in a single character and determines if ! it is a vowel, a consonant, a digit, one of the four
! arithmetic operators (+, -, * and /), a space, or something ! else. You can do it with IF-THEN-ELSE-END IF statement; but ! SELECT CASE statement provides a cleaner solution.
!
! For character input, you could use the quote characters like ! 'G'
! Or, just type the character. In this case, the first ! character you type will be read.
!
---PROGRAM CharacterTesting IMPLICIT NONE
CHARACTER(LEN=1) :: Input
READ(*,*) Input
SELECT CASE (Input)
CASE ('A' : 'Z', 'a' : 'z') ! rule out letters WRITE(*,*) 'A letter is found : "', Input, '"' SELECT CASE (Input) ! a vowel ?
CASE ('A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o','u') WRITE(*,*) 'It is a vowel'
CASE DEFAULT ! it must be a consonant WRITE(*,*) 'It is a consonant'
END SELECT
CASE ('0' : '9') ! a digit
WRITE(*,*) 'A digit is found : "', Input, '"' CASE ('+', '-', '*', '/') ! an operator
WRITE(*,*) 'An operator is found : "', Input, '"' CASE (' ') ! space
END PROGRAM CharacterTesting
Click here to download this program.
P
ROGRAMI
NPUT ANDO
UTPUTHow do you input a character to your program? The easiest way is using something like 'Y', "g" and '-'. That is, use single or double quotes.
If the input character is s, the program should report it is a consonant.
A letter is found : "s" It is a consonant
If the input character is U, the program should report it is a vowel.
A letter is found : "U" It is a vowel
If the input character is 8, the program should report it is a digit.
A digit is found : "8"
If the input character is +, the program should report it is an operator.
An operator is found : "+"
If the input character is a space, the program should report it is a space.
A space is found : " "
If the input character is none of the above, say &, the program should report it is something else.
Something else found : "&"