Expressions Outline Expressions a + b - * d / e ** f - 398 + g * 5981 / 15 ** h 1. Arithmetic Expressions Outline 2. Expressions In programming, an expression is a combination of:

3. Arithmetic Expressions , such as: 4. Unary & Binary Arithmetic Operations – Literal constants 5. Structure of Arithmetic Expressions/ – Named constants Jargon: INTEGER-valued & REAL-valued Expressions – Variables 6. Precedence Order of Arithmetic Operations – Function invocations (which we’ll discuss later) 7. Arithmetic Precedence Order Example: INTEGER Operands Operators, such as: 8. Arithmetic Precedence Order Example: REAL Operands – Arithmetic Operators 9. Named Constants & Variables as Operands ¡ : + 10. Constant-Valued Expressions in Named Constant Initializations ¡ Subtraction: - 11. Assignments Using Expressions ¡ Multiplication: * 12. Using the Same Variable on Both Sides of an Assignment ¡ Division: / 13. The Meaning of Using the Same Variable on Both Sides of an ¡ Exponentiation: ** Assignment – Relational Operators 14. Single Mode Arithmetic ¡ Equal: == 15. Division By Zero ¡ Not Equal: /= 16. Mixed Mode Arithmetic ¡ Less Than: < 17. A Mixed Mode Arithmetic Example ¡ Less Than or Equal To: <= 18. Exercise: Writing a Program ¡ Greater Than: > ¡ Greater Than or Equal To: >= – Logical Operators See Programming in Fortran 90/95, 1st or 2nd ed, Chapter 10. ¡ Negation: .NOT. ¡ Conjunction: .AND. ¡ Disjunction: .OR.

Parentheses Not surprisingly, an expression in a program can look very much like an expression in math (though not identical). This is on purpose.

1 2 Arithmetic Expressions Unary & Binary Arithmetic Operations An arithmetic expression (also called a numeric expression) is a Arithmetic operations come in two varieties: unary and binary. combination of:

Numeric Operands, such as: A unary is an operation that has only one . For – INTEGER & REAL literal constants (BAD BAD BAD) example: INTEGER REAL – & named constants (GOOD) -x – INTEGER & REAL variables – INTEGER-valued & REAL-valued function invocations Here, the operand is x, the operator is the minus sign, and the oper- Arithmetic Operators, such as: ation is negation. – Identity: + – Negation: - A uses two operands. For example: – Addition: + – Subtraction: - y + z – Multiplication: * – Division: / Here, the operands are y and z, the operator is the plus sign, and the – Exponentiation: ** operation is addition. Parentheses Arithmetic operations are: Some Arithmetic Expression Examples Operation Kind Operator Usage Value x Identity Unary + +x Value of x +x None x Value of x -x Negation Unary - -x of x x + y Addition Binary + x + y Sum of x and y Subtraction Binary - x - y Difference between x and y ¢ x - y Multiplication Binary * x * y Product of x times y (i.e., ¡ ) £ x * y Division Binary / x / y Quotient of x over y (i.e., ¢ ) ¤ x / y Exponentiation Binary ** x ** y x to the power y (i.e., ) x ** y x + y - (z / 22) * 7

3 4 Structure of Arithmetic Expressions Precedence Order of Arithmetic Operations An arithmetic expression can be long and complicated. For example: In the absence of parentheses that explicitly state the order of opera- a + b - c * d / e ** f tions, the order of precedence (also called order of priority) is:

Terms and operators can be mixed together in almost limitless vari- First: exponentiation, right to left, followed by ety, but they must follow the rule that a unary operator has a term Second: multiplication and division, left to right, and finally immediately to its right and a binary operator has terms on both its Third: addition, subtraction, identity and negation, left to right left and its right: After taking into account the above rules, the expression as a whole -a + b - c * d / e ** f - 398 + g * 5981 / 15 ** h is evaluated left to right. For example:

Parentheses can be placed around any unary or binary expression: 1 - 2 - 3 -1 - 3 -4 but (-a + b - c) * d / e ** ((f-398) + g * 5981 / 15) ** h 1 - (2 - 3) 1 - (-1) 2

1 + 2 * 3 + 4 1 + 6 + 4 7 + 4 11 but

Putting a term in parentheses may change the value of the expres- (1 + 2) * 3 + 4 3 * 3 + 4 9 + 4 13

sion, because a term inside parentheses will be calculated first. For 24 / 2 * 4 12 * 4 48 but

example: 24 / (2 * 4) 24 / 8 3

a + b * c is evaluated as “multiply b by c, then add a” 5 + 3 ** 6 / 3 5 + 729 / 3 5 + 243 248 but but 5 + 3 ** (6 / 3) 5 + 3 ** 2 5 + 9 14 but (5 + 3) ** (6 / 3) 8 ** (6 / 3) 8 ** 2 64 (a + b) * c

is evaluated as “add a and b, then multiply by c” -2 ** 4 -16 but

Note: as a general rule, you cannot put two operators in a row. (-2) ** 4 16

Jargon: -2 ** 3 ** 2 -512 but INTEGER-valued & REAL-valued (-2 ** 3) ** 2 64 Expressions Rule of Thumb: if you can’t remember the precedence order of the An INTEGER-valued expression is an expression whose result, when operators, use lots of parentheses. evaluated, is an INTEGER.

A REAL-valued expression is an expression whose result, when eval- uated, is a REAL.

5 6 Arithmetic Precedence Order Example: Arithmetic Precedence Order Example: INTEGER Operands REAL Operands % cat realexprs.f90 PROGRAM realexprs % cat intexprs.f90 IMPLICIT NONE PROGRAM intexprs PRINT *, '1.0 - 2.0 - 3.0 = ', 1.0 - 2.0 - 3.0 IMPLICIT NONE PRINT *, '1.0 - (2.0 - 3.0) = ', 1.0 - (2.0 - 3.0) PRINT *, '1 - 2 - 3 = ', 1 - 2 - 3 PRINT *, "" PRINT *, '1 - (2 - 3) = ', 1 - (2 - 3) PRINT *, ' 1.0 + 2.0 * 3.0 + 4.0 = ', & PRINT *, "" & 1.0 + 2.0 * 3.0 + 4.0 PRINT *, ' 1 + 2 * 3 + 4 = ', 1 + 2 * 3 + 4 PRINT *, '(1.0 + 2.0) * 3.0 + 4.0 = ', & PRINT *, '(1 + 2) * 3 + 4 = ', (1 + 2) * 3 + 4 & (1.0 + 2.0) * 3.0 + 4.0 PRINT *, "" PRINT *, "" PRINT *, '24 / 2 * 4 = ', 24 / 2 * 4 PRINT *, '24.0 / 2.0 * 4.0 = ', 24.0 / 2.0 * 4.0 PRINT *, '24 / (2 * 4) = ', 24 / (2 * 4) PRINT *, '24.0 / (2.0 * 4.0) = ', 24.0 / (2.0 * 4.0) PRINT *, "" PRINT *, "" PRINT *, ' 5 + 3 ** 6 / 3 = ', 5 + 3 ** 6 / 3 PRINT *, ' 5.0 + 3.0 ** 6.0 / 3.0 = ', & PRINT *, ' 5 + 3 ** (6 / 3) = ', 5 + 3 ** (6 / 3) & 5.0 + 3.0 ** 6.0 / 3.0 PRINT *, '(5 + 3) ** (6 / 3) = ', (5 + 3) ** (6 / 3) PRINT *, ' 5.0 + 3.0 ** (6.0 / 3.0) = ', & PRINT *, "" & 5.0 + 3.0 ** (6.0 / 3.0) PRINT *, ' -2 ** 4 = ', -2 ** 4 PRINT *, '(5.0 + 3.0) ** (6.0 / 3.0) = ', & PRINT *, '(-2) ** 4 = ', (-2) ** 4 & (5.0 + 3.0) ** (6.0 / 3.0) PRINT *, "" PRINT *, "" PRINT *, ' 2 ** 3 ** 2 = ', 2 ** 3 ** 2 PRINT *, ' -2.0 ** 4.0 = ', -2.0 ** 4.0 PRINT *, ' (2 ** 3) ** 2 = ', (2 ** 3) ** 2 PRINT *, '(-2.0) ** 4 = ', (-2.0) ** 4 END PROGRAM intexprs PRINT *, "" % f95 -o intexprs intexprs.f90 PRINT *, ' 2.0 ** 3.0 ** 2.0 = ', & % intexprs & 2.0 ** 3.0 ** 2.0 1 - 2 - 3 = -4 PRINT *, ' (2.0 ** 3.0) ** 2.0 = ', & 1 - (2 - 3) = 2 & (2.0 ** 3.0) ** 2.0 END PROGRAM realexprs 1 + 2 * 3 + 4 = 11 % f95 -o realexprs realexprs.f90 (1 + 2) * 3 + 4 = 13 % realexprs 1.0 - 2.0 - 3.0 = -4.0000000 24 / 2 * 4 = 48 1.0 - (2.0 - 3.0) = 2.0000000 24 / (2 * 4) = 3 1.0 + 2.0 * 3.0 + 4.0 = 11.0000000 5 + 3 ** 6 / 3 = 248 (1.0 + 2.0) * 3.0 + 4.0 = 13.0000000 5 + 3 ** (6 / 3) = 14 (5 + 3) ** (6 / 3) = 64 24.0 / 2.0 * 4.0 = 48.0000000 24.0 / (2.0 * 4.0) = 3.0000000 -2 ** 4 = -16 (-2) ** 4 = 16 5.0 + 3.0 ** 6.0 / 3.0 = 2.4800000E+02 5.0 + 3.0 ** (6.0 / 3.0) = 14.0000000 2 ** 3 ** 2 = 512 (5.0 + 3.0) ** (6.0 / 3.0) = 64.0000000 (2 ** 3) ** 2 = 64 -2.0 ** 4.0 = -16.0000000 Notice that a PRINT statement can output the value of an expres- (-2.0) ** 4 = 16.0000000 2.0 ** 3.0 ** 2.0 = 5.1200000E+02 sion. (2.0 ** 3.0) ** 2.0 = 64.0000000

7 8 Named Constants & Variables as Operands Constant-Valued Expressions in Named Constant Initializations So far, many of the examples of expressions that we’ve looked at have used numeric literal constants as operands. If we have an expression whose terms are all constants (either literal constants or named constants), then we can use that expression in But of course we already know that using numeric literal constants the initialization of a named constant: in the body of a program is BAD BAD BAD. % cat constexpr.f90 PROGRAM constant_expression So instead, we want to use named constants and variables as operands: IMPLICIT NONE REAL,PARAMETER :: & % cat age.f90 & C_to_F_factor = 9.0 / 5.0 PROGRAM age REAL,PARAMETER :: & IMPLICIT NONE & C_to_F_increase = 32.0 INTEGER,PARAMETER :: days_in_a_year = 365 REAL,PARAMETER :: & INTEGER,PARAMETER :: hours_in_a_day = 24 & C_water_boiling_temperature = 100.0 INTEGER,PARAMETER :: minutes_in_an_hour = 60 REAL,PARAMETER :: & INTEGER,PARAMETER :: seconds_in_a_minute = 60 & F_water_boiling_temperature = & INTEGER :: year_of_birth, current_year & C_water_boiling_temperature * & PRINT *, "Let me guess your age in seconds!" & C_to_F_factor + & PRINT *, "What year were you born?" & C_to_F_increase READ *, year_of_birth PRINT *, "Water boils at ", & PRINT *, "What year is this?" & C_water_boiling_temperature, & READ *, current_year & " degrees C," PRINT *, "I'd guess that your age is about ", & PRINT *, " which is ", & & (current_year - year_of_birth) * & & F_water_boiling_temperature, & & days_in_a_year * hours_in_a_day * & & " degrees F." & minutes_in_an_hour * seconds_in_a_minute, & END PROGRAM constant_expression & " seconds." % f95 -o constexpr constexpr.f90 END PROGRAM age % constexpr % f95 -o age age.f90 Water boils at 1.0000000E+02 degrees C, % age which is 2.1200000E+02 degrees F. Let me guess your age in seconds! What year were you born? 1965 Note: in the initialization of a named constant, we cannot have an What year is this? 2000 expression whose value is not constant. I'd guess that your age is about 1103760000 seconds.

Again notice that PRINT statements can output expressions.

9 10 Assignments Using Expressions Using the Same Variable on Both Sides So far, many of the assignment statements that we’ve seen have sim- of an Assignment ply assigned a literal value to a variable: Suppose we have an expression on the right side of an assignment: % cat varassn.f90 PROGRAM variable_assignment x = y + 1 IMPLICIT NONE INTEGER :: x The compiler interprets the assignment statement to mean, “first, x = 5 evaluate the expression that’s on the right side of the assignment; PRINT *, 'x = ', x then, put the resulting value into the variable that’s on the left side END PROGRAM variable_assignment of the assignment.” In this case, the assignment statement means, % f95 -o varassn varassn.f90 % varassn “evaluate y + 1, then put the resulting value into x.” x = 5 % cat xgetsyplus1.f90 But, the meat and potatoes of computing is the assignment of com- PROGRAM x_assign_y_plus_1 plicated expressions: IMPLICIT NONE INTEGER :: x, y % cat triangarea.f90 y = 5 PROGRAM triangarea PRINT *, "y = ", y IMPLICIT NONE REAL,PARAMETER :: height_factor = 0.5 x = y + 1 REAL :: base, height, area PRINT *, "x = ", x PRINT *, "This program calculates the area of a" END PROGRAM x_assign_y_plus_1 PRINT *, " triangle from its base and height." % f95 -o xgetsyplus1 xgetsyplus1.f90 PRINT *, "What are the base and height?" READ *, base, height % xgetsyplus1 area = height_factor * base * height y = 5 PRINT *, "The area of a triangle of base ", base x = 6 PRINT *, " and height ", height, " is ", area, "." END PROGRAM triangarea % f95 -o triangarea triangarea.f90 Here’s another assignment: % triangarea This program calculates the area of a x = x + 1 triangle from its base and height. What are the base and height? 5 7 The assignment statement above may be confusing, because it has The area of a triangle of base 5.0000000 the same variable, x, on both the left side and the right side of the and height 7.0000000 is 17.5000000 . assignment statement.

11 12 The Meaning of Using Single Mode Arithmetic the Same Variable on Both Sides In Fortran 90, when we have an arithmetic expression whose terms of an Assignment all evaluate to a single data type (e.g., all INTEGER-valued terms or all REAL-valued terms), we call this single mode arithmetic. x = x + 1

In general, the compiler interprets an assignment statement to mean, In Fortran 90, single mode INTEGER arithmetic behaves like single “first, evaluate the expression that’s on the right side of the assign- mode REAL arithmetic most of the time. For example, ment; then, put the resulting value into the variable that’s on the left 5.0 + 7.0 = 12.0 and side of the assignment.” 5 + 7 = 12 5.0 - 7.0 = -2.0 and 5 - 7 = -2 So, the assignment statement above means, “get the current value of 5.0 * 7.0 = 35.0 and x, then add 1 to it, then place the new value back into x.” 5 * 7 = 35 But, division is different for INTEGERs and REALs! % cat assignself.f90 PROGRAM assignself 5.0 / 7.0 = 0.71 but IMPLICIT NONE 5 / 7 = 0 INTEGER :: x REAL division in Fortran 90 works the same way division works in x = 5 mathematics. But INTEGER division is a little bit strange. PRINT *, "After 1st assignment, x = ", x x = x + 1 PRINT *, "After 2nd assignment, x = ", x In INTEGER division, the result is TRUNCATED to the nearest END PROGRAM assignself INTEGER immediately less than the mathematical result; e.g., % f95 -o assignself assignself.f90 4.0 / 4.0 = 1.00 and % assignself 5 / 4 = 1 After 1st assignment, x = 5 5.0 / 4.0 = 1.25 but After 2nd assignment, x = 6 5 / 4 = 1 6.0 / 4.0 = 1.5 but 6 / 4 = 1 7.0 / 4.0 = 1.75 but 7 / 4 = 1 8.0 / 4.0 = 2.0 and 8 / 4 = 2

13 14 Division By Zero Mixed Mode Arithmetic Mathematically, division by zero gives an infinite result: In principle, we might like our numeric statements to have either all

§ ¤ ¡ £ ¥ ¦ ¢ ¢ INTEGER-valued terms or all REAL-valued terms. ¡ Computationally, division by zero causes an error. Some compilers In practice, though, we can freely mix INTEGER-valued and REAL- won’t even compile it: % cat divbyzeroconst.f90 valued literals, variables and expressions, subject to the rule that an PROGRAM divbyzeroconst operation with operands of both types has a REAL result. IMPLICIT NONE PRINT *, '5 / 0 = ', 5 / 0 END PROGRAM divbyzeroconst We call such expressions mixed mode arithmetic. % f95 -o divbyzeroconst divbyzeroconst.f90 Error: divbyzeroconst.f90, line 3: Integer divide by zero 1 + 2 = 3 and [f95 error termination] 1 + 2.0 = 3.0 If you manage to slip a zero denominator past the compiler, the pro- 1 / 2 = 0 but gram will crash: 1 / 2.0 = 0.5 % cat divbyzero.f90 3 ** 2 = 9 and PROGRAM divbyzero IMPLICIT NONE 3.0 ** 2 = 9.0 and INTEGER :: numerator, denominator 3.0 ** 2.0 = 9.0 PRINT *, "What's the numerator?" READ *, numerator 4 ** (1 / 2) = 1 and PRINT *, "What's the denominator?" 4.0 ** (1 / 2) = 1.0 but READ *, denominator PRINT *, 'numerator = ', numerator 4.0 ** (1 / 2.0) = 2.0 PRINT *, 'denominator = ', denominator INTEGER PRINT *, 'numerator / denominator = ', & For mixed mode arithmetic, we say that an operand is & numerator / denominator promoted to REAL. END PROGRAM divbyzero % f95 -o divbyzero divbyzero.f90 1 / 2 = 0 but % divbyzero What's the numerator? 5 1 / 2.0 = What's the denominator? 1.0 / 2.0 = 0.5 0 numerator = 5 4.0 ** (1 / 2) = 1.0 but denominator = 0 *** Arithmetic exception: - aborting Abort (core dumped) 4.0 ** (1 / 2.0) = 4.0 ** (1.0 / 2.0) = 2.0

15 16 A Mixed Mode Arithmetic Example Exercise: Writing a Program ¢ Let be the temperature in degrees Celsius. Let be the temperature 5 * ( 11.0 - 5 ¡ ) ** 2 / 4 + 9 => in degrees Fahrenheit. Then: 5 * ( 11.0 - 5.0 ) ** 2 / 4 + 9 => £ ¢ ¦§ ¥

¢

5 * ( [11.0 - 5.0] ) ** 2 / 4 + 9 => ¤ 5 * 6.0 ** 2 / 4 + 9 => Write a Fortran 90 program that prompts the user and then inputs a 5 * 6.0 ** 2 ¡ / 4 + 9 => temperature in degrees Celsius, calculates the temperature in degrees 5 * 6.0 ** 2.0 / 4 + 9 => Fahrenheit, then outputs the temperature in degrees Fahrenheit. 5 * [ 6.0 ** 2.0 ] / 4 + 9 => 5 * 36.0 / 4 + 9 => The body of the program must not have any numeric literal con- stants; all constants must be declared using appropriate symbolic ¡ 5 * 36.0 / 4 + 9 => names. 5.0 * 36.0 / 4 + 9 =>

[5.0 * 36.0] / 4 + 9 => Don’t worry about comments. 180.0 / 4 + 9 =>

180.0 / 4 ¡ + 9 => 180.0 / 4.0 + 9 =>

[180.0 / 4.0] + 9 => 45.0 + 9 =>

45.0 + 9 ¡ => 45.0 + 9.0 =>

[45.0 + 9.0] => 54.0

Note: values in curly braces ¡ are about to be converted from INTEGER to REAL; expressions in square brackets [ ] are about to be calculated.

17 18