Expressions Outline 1. Arithmetic Expressions Outline 2. Expressions 3. Arithmetic Expressions 4. Unary & Binary Arithmetic Operations 5. Structure of Arithmetic Expressions/ Jargon: INTEGER-valued & REAL-valued Expressions 6. Precedence Order of Arithmetic Operations 7. Arithmetic Precedence Order Example: INTEGER 8. Arithmetic Precedence Order Example: REAL Operands 9. Named Constants & Variables as Operands 10. Constant-Valued Expressions in Named Constant Initializations 11. Assignments Using Expressions 12. Using the Same Variable on Both Sides of an Assignment 13. The Meaning of Using the Same Variable on Both Sides of an Assignment 14. Single Mode Arithmetic 15. Division By Zero 16. Mixed Mode Arithmetic 17. A Mixed Mode Arithmetic Example 18. Exercise: Writing a Program

See Programming in Fortran 90/95, 1st or 2nd ed, Chapter 10.

1 Expressions a + b - * d / e ** f - 398 + g * 5981 / 15 ** h In programming, an expression is a combination of: • Operands, such as: – Literal constants – Named constants – Variables – Function invocations (which we’ll discuss later) • Operators, such as: – Arithmetic Operators ∗ : + ∗ Subtraction: - ∗ Multiplication: * ∗ Division: / ∗ Exponentiation: ** – Relational Operators ∗ Equal: == ∗ Not Equal: /= ∗ Less Than: < ∗ Less Than or Equal To: <= ∗ Greater Than: > ∗ Greater Than or Equal To: >= – Logical Operators ∗ 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.

2 Arithmetic Expressions An arithmetic expression (also called a numeric expression) is a combination of: • Numeric Operands, such as: – INTEGER & REAL literal constants (BAD BAD BAD) – INTEGER & REAL named constants (GOOD) – INTEGER & REAL variables – INTEGER-valued & REAL-valued function invocations • Arithmetic Operators, such as: – Identity: + – Negation: - – Addition: + – Subtraction: - – Multiplication: * – Division: / – Exponentiation: ** • Parentheses

Some Arithmetic Expression Examples x +x -x x + y x - y x * y x / y x ** y x + y - (z / 22) * 7

3 Unary & Binary Arithmetic Operations Arithmetic operations come in two varieties: unary and binary.

A unary is an operation that has only one . For example: -x

Here, the operand is x, the operator is the minus sign, and the oper- ation is negation.

A uses two operands. For example: y + z

Here, the operands are y and z, the operator is the plus sign, and the operation is addition.

Arithmetic operations are:

Operation Kind Operator Usage Value Identity Unary + +x Value of x None x Value of x Negation Unary - -x of x Addition Binary + x + y Sum of x and y Subtraction Binary - x - y Difference between x and 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., xy)

4 Structure of Arithmetic Expressions An arithmetic expression can be long and complicated. For example: a + b - c * d / e ** f Terms and operators can be mixed together in almost limitless vari- ety, but they must follow the rule that a unary operator has a term immediately to its right and a binary operator has terms on both its left and its right: -a + b - c * d / e ** f - 398 + g * 5981 / 15 ** h Parentheses can be placed around any unary or binary expression: (-a + b - c) * d / e ** ((f-398) + g * 5981 / 15) ** h Putting a term in parentheses may change the value of the expres- sion, because a term inside parentheses will be calculated first. For example: a + b * c is evaluated as “multiply b by c, then add a” but (a + b) * c is evaluated as “add a and b, then multiply by c” Note: as a general rule, you cannot put two operators in a row. Jargon: INTEGER-valued & REAL-valued Expressions An INTEGER-valued expression is an expression whose result, when evaluated, is an INTEGER.

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

5 Precedence Order of Arithmetic Operations In the absence of parentheses that explicitly state the order of opera- tions, the order of precedence (also called order of priority) is: • First: exponentiation, right to left, followed by • Second: multiplication and division, left to right, and finally • Third: addition, subtraction, identity and negation, left to right After taking into account the above rules, the expression as a whole is evaluated left to right. For example:

• 1 - 2 - 3 ≡ -1 - 3 ≡ -4 but 1 - (2 - 3) ≡ 1 - (-1) ≡ 2 • 1 + 2 * 3 + 4 ≡ 1 + 6 + 4 ≡ 7 + 4 ≡ 11 but (1 + 2) * 3 + 4 ≡ 3 * 3 + 4 ≡ 9 + 4 ≡ 13 • 24 / 2 * 4 ≡ 12 * 4 ≡ 48 but 24 / (2 * 4) ≡ 24 / 8 ≡ 3 • 5 + 3 ** 6 / 3 ≡ 5 + 729 / 3 ≡ 5 + 243 ≡ 248 but 5 + 3 ** (6 / 3) ≡ 5 + 3 ** 2 ≡ 5 + 9 ≡ 14 but (5 + 3) ** (6 / 3) ≡ 8 ** (6 / 3) ≡ 8 ** 2 ≡ 64 • -2 ** 4 ≡ -16 but (-2) ** 4 ≡ 16 • -2 ** 3 ** 2 ≡ -512 but (-2 ** 3) ** 2 ≡ 64

Rule of Thumb: if you can’t remember the precedence order of the operators, use lots of parentheses.

6 Arithmetic Precedence Order Example: INTEGER Operands

% cat intexprs.f90 PROGRAM intexprs IMPLICIT NONE PRINT *, ’1 - 2 - 3 = ’, 1 - 2 - 3 PRINT *, ’1 - (2 - 3) = ’, 1 - (2 - 3) PRINT *, "" PRINT *, ’ 1 + 2 * 3 + 4 = ’, 1 + 2 * 3 + 4 PRINT *, ’(1 + 2) * 3 + 4 = ’, (1 + 2) * 3 + 4 PRINT *, "" PRINT *, ’24 / 2 * 4 = ’, 24 / 2 * 4 PRINT *, ’24 / (2 * 4) = ’, 24 / (2 * 4) PRINT *, "" PRINT *, ’ 5 + 3 ** 6 / 3 = ’, 5 + 3 ** 6 / 3 PRINT *, ’ 5 + 3 ** (6 / 3) = ’, 5 + 3 ** (6 / 3) PRINT *, ’(5 + 3) ** (6 / 3) = ’, (5 + 3) ** (6 / 3) PRINT *, "" PRINT *, ’ -2 ** 4 = ’, -2 ** 4 PRINT *, ’(-2) ** 4 = ’, (-2) ** 4 PRINT *, "" PRINT *, ’ 2 ** 3 ** 2 = ’, 2 ** 3 ** 2 PRINT *, ’ (2 ** 3) ** 2 = ’, (2 ** 3) ** 2 END PROGRAM intexprs % f95 -o intexprs intexprs.f90 % intexprs 1 - 2 - 3 = -4 1 - (2 - 3) = 2

1 + 2 * 3 + 4 = 11 (1 + 2) * 3 + 4 = 13

24 / 2 * 4 = 48 24 / (2 * 4) = 3

5 + 3 ** 6 / 3 = 248 5 + 3 ** (6 / 3) = 14 (5 + 3) ** (6 / 3) = 64

-2 ** 4 = -16 (-2) ** 4 = 16

2 ** 3 ** 2 = 512 (2 ** 3) ** 2 = 64

Notice that a PRINT statement can output the value of an expres- sion.

7 Arithmetic Precedence Order Example: REAL Operands % cat realexprs.f90 PROGRAM realexprs IMPLICIT NONE PRINT *, ’1.0 - 2.0 - 3.0 = ’, 1.0 - 2.0 - 3.0 PRINT *, ’1.0 - (2.0 - 3.0) = ’, 1.0 - (2.0 - 3.0) PRINT *, "" PRINT *, ’ 1.0 + 2.0 * 3.0 + 4.0 = ’, & & 1.0 + 2.0 * 3.0 + 4.0 PRINT *, ’(1.0 + 2.0) * 3.0 + 4.0 = ’, & & (1.0 + 2.0) * 3.0 + 4.0 PRINT *, "" PRINT *, ’24.0 / 2.0 * 4.0 = ’, 24.0 / 2.0 * 4.0 PRINT *, ’24.0 / (2.0 * 4.0) = ’, 24.0 / (2.0 * 4.0) PRINT *, "" PRINT *, ’ 5.0 + 3.0 ** 6.0 / 3.0 = ’, & & 5.0 + 3.0 ** 6.0 / 3.0 PRINT *, ’ 5.0 + 3.0 ** (6.0 / 3.0) = ’, & & 5.0 + 3.0 ** (6.0 / 3.0) PRINT *, ’(5.0 + 3.0) ** (6.0 / 3.0) = ’, & & (5.0 + 3.0) ** (6.0 / 3.0) PRINT *, "" PRINT *, ’ -2.0 ** 4.0 = ’, -2.0 ** 4.0 PRINT *, ’(-2.0) ** 4 = ’, (-2.0) ** 4 PRINT *, "" PRINT *, ’ 2.0 ** 3.0 ** 2.0 = ’, & & 2.0 ** 3.0 ** 2.0 PRINT *, ’ (2.0 ** 3.0) ** 2.0 = ’, & & (2.0 ** 3.0) ** 2.0 END PROGRAM realexprs % f95 -o realexprs realexprs.f90 % realexprs 1.0 - 2.0 - 3.0 = -4.0000000 1.0 - (2.0 - 3.0) = 2.0000000

1.0 + 2.0 * 3.0 + 4.0 = 11.0000000 (1.0 + 2.0) * 3.0 + 4.0 = 13.0000000

24.0 / 2.0 * 4.0 = 48.0000000 24.0 / (2.0 * 4.0) = 3.0000000

5.0 + 3.0 ** 6.0 / 3.0 = 2.4800000E+02 5.0 + 3.0 ** (6.0 / 3.0) = 14.0000000 (5.0 + 3.0) ** (6.0 / 3.0) = 64.0000000

-2.0 ** 4.0 = -16.0000000 (-2.0) ** 4 = 16.0000000

2.0 ** 3.0 ** 2.0 = 5.1200000E+02 (2.0 ** 3.0) ** 2.0 = 64.0000000

8 Named Constants & Variables as Operands So far, many of the examples of expressions that we’ve looked at have used numeric literal constants as operands.

But of course we already know that using numeric literal constants in the body of a program is BAD BAD BAD.

So instead, we want to use named constants and variables as operands:

% cat age.f90 PROGRAM age IMPLICIT NONE INTEGER,PARAMETER :: days_in_a_year = 365 INTEGER,PARAMETER :: hours_in_a_day = 24 INTEGER,PARAMETER :: minutes_in_an_hour = 60 INTEGER,PARAMETER :: seconds_in_a_minute = 60 INTEGER :: year_of_birth, current_year PRINT *, "Let me guess your age in seconds!" PRINT *, "What year were you born?" READ *, year_of_birth PRINT *, "What year is this?" READ *, current_year PRINT *, "I’d guess that your age is about ", & & (current_year - year_of_birth) * & & days_in_a_year * hours_in_a_day * & & minutes_in_an_hour * seconds_in_a_minute, & & " seconds." END PROGRAM age % f95 -o age age.f90 % age Let me guess your age in seconds! What year were you born? 1965 What year is this? 2000 I’d guess that your age is about 1103760000 seconds.

Again notice that PRINT statements can output expressions.

9 Constant-Valued Expressions in Named Constant Initializations If we have an expression whose terms are all constants (either literal constants or named constants), then we can use that expression in the initialization of a named constant:

% cat constexpr.f90 PROGRAM constant_expression IMPLICIT NONE REAL,PARAMETER :: & & C_to_F_factor = 9.0 / 5.0 REAL,PARAMETER :: & & C_to_F_increase = 32.0 REAL,PARAMETER :: & & C_water_boiling_temperature = 100.0 REAL,PARAMETER :: & & F_water_boiling_temperature = & & C_water_boiling_temperature * & & C_to_F_factor + & & C_to_F_increase PRINT *, "Water boils at ", & & C_water_boiling_temperature, & & " degrees C," PRINT *, " which is ", & & F_water_boiling_temperature, & & " degrees F." END PROGRAM constant_expression % f95 -o constexpr constexpr.f90 % constexpr Water boils at 1.0000000E+02 degrees C, which is 2.1200000E+02 degrees F.

Note: in the initialization of a named constant, we cannot have an expression whose value is not constant.

10 Assignments Using Expressions So far, many of the assignment statements that we’ve seen have sim- ply assigned a literal value to a variable: % cat varassn.f90 PROGRAM variable_assignment IMPLICIT NONE INTEGER :: x x = 5 PRINT *, ’x = ’, x END PROGRAM variable_assignment % f95 -o varassn varassn.f90 % varassn x = 5 But, the meat and potatoes of computing is the assignment of com- plicated expressions: % cat triangarea.f90 PROGRAM triangarea IMPLICIT NONE REAL,PARAMETER :: height_factor = 0.5 REAL :: base, height, area PRINT *, "This program calculates the area of a" PRINT *, " triangle from its base and height." PRINT *, "What are the base and height?" READ *, base, height area = height_factor * base * height PRINT *, "The area of a triangle of base ", base PRINT *, " and height ", height, " is ", area, "." END PROGRAM triangarea % f95 -o triangarea triangarea.f90 % triangarea This program calculates the area of a triangle from its base and height. What are the base and height? 5 7 The area of a triangle of base 5.0000000 and height 7.0000000 is 17.5000000 .

11 Using the Same Variable on Both Sides of an Assignment Suppose we have an expression on the right side of an assignment: x = y + 1

The compiler interprets the assignment statement to mean, “first, evaluate the expression that’s on the right side of the assignment; then, put the resulting value into the variable that’s on the left side of the assignment.” In this case, the assignment statement means, “evaluate y + 1, then put the resulting value into x.” % cat xgetsyplus1.f90 PROGRAM x_assign_y_plus_1 IMPLICIT NONE INTEGER :: x, y y = 5 PRINT *, "y = ", y x = y + 1 PRINT *, "x = ", x END PROGRAM x_assign_y_plus_1 % f95 -o xgetsyplus1 xgetsyplus1.f90 % xgetsyplus1 y = 5 x = 6

Here’s another assignment: x = x + 1

The assignment statement above may be confusing, because it has the same variable, x, on both the left side and the right side of the assignment statement.

12 The Meaning of Using the Same Variable on Both Sides of an Assignment x = x + 1

In general, the compiler interprets an assignment statement to mean, “first, evaluate the expression that’s on the right side of the assign- ment; then, put the resulting value into the variable that’s on the left side of the assignment.”

So, the assignment statement above means, “get the current value of x, then add 1 to it, then place the new value back into x.”

% cat assignself.f90 PROGRAM assignself IMPLICIT NONE INTEGER :: x x = 5 PRINT *, "After 1st assignment, x = ", x x = x + 1 PRINT *, "After 2nd assignment, x = ", x END PROGRAM assignself % f95 -o assignself assignself.f90 % assignself After 1st assignment, x = 5 After 2nd assignment, x = 6

13 Single Mode Arithmetic In Fortran 90, when we have an arithmetic expression whose terms all evaluate to a single data type (e.g., all INTEGER-valued terms or all REAL-valued terms), we call this single mode arithmetic.

In Fortran 90, single mode INTEGER arithmetic behaves like single mode REAL arithmetic most of the time. For example, 5.0 + 7.0 = 12.0 and 5 + 7 = 12 5.0 - 7.0 = -2.0 and 5 - 7 = -2 5.0 * 7.0 = 35.0 and 5 * 7 = 35 But, division is different for INTEGERs and REALs! 5.0 / 7.0 = 0.71 but 5 / 7 = 0 REAL division in Fortran 90 works the same way division works in mathematics. But INTEGER division is a little bit strange.

In INTEGER division, the result is TRUNCATED to the nearest INTEGER immediately less than the mathematical result; e.g., 4.0 / 4.0 = 1.00 and 5 / 4 = 1 5.0 / 4.0 = 1.25 but 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

14 Division By Zero Mathematically, division by zero gives an infinite result: c = ∞ for c =6 0 0 Computationally, division by zero causes an error. Some compilers won’t even compile it: % cat divbyzeroconst.f90 PROGRAM divbyzeroconst IMPLICIT NONE PRINT *, ’5 / 0 = ’, 5 / 0 END PROGRAM divbyzeroconst % f95 -o divbyzeroconst divbyzeroconst.f90 Error: divbyzeroconst.f90, line 3: Integer divide by zero [f95 error termination] If you manage to slip a zero denominator past the compiler, the pro- gram will crash: % cat divbyzero.f90 PROGRAM divbyzero IMPLICIT NONE INTEGER :: numerator, denominator PRINT *, "What’s the numerator?" READ *, numerator PRINT *, "What’s the denominator?" READ *, denominator PRINT *, ’numerator = ’, numerator PRINT *, ’denominator = ’, denominator PRINT *, ’numerator / denominator = ’, & & numerator / denominator END PROGRAM divbyzero % f95 -o divbyzero divbyzero.f90 % divbyzero What’s the numerator? 5 What’s the denominator? 0 numerator = 5 denominator = 0 *** Arithmetic exception: - aborting Abort (core dumped)

15 Mixed Mode Arithmetic In principle, we might like our numeric statements to have either all INTEGER-valued terms or all REAL-valued terms.

In practice, though, we can freely mix INTEGER-valued and REAL- valued literals, variables and expressions, subject to the rule that an operation with operands of both types has a REAL result.

We call such expressions mixed mode arithmetic. 1 + 2 = 3 and 1 + 2.0 = 3.0 1 / 2 = 0 but 1 / 2.0 = 0.5 3 ** 2 = 9 and 3.0 ** 2 = 9.0 and 3.0 ** 2.0 = 9.0 4 ** (1 / 2) = 1 and 4.0 ** (1 / 2) = 1.0 but 4.0 ** (1 / 2.0) = 2.0 For mixed mode arithmetic, we say that an INTEGER operand is promoted to REAL. 1 / 2 = 0 but

1 / 2.0 = 1.0 / 2.0 = 0.5 4.0 ** (1 / 2) = 1.0 but

4.0 ** (1 / 2.0) = 4.0 ** (1.0 / 2.0) = 2.0

16 A Mixed Mode Arithmetic Example

5 * ( 11.0 - { 5 } ) ** 2 / 4 + 9 => 5 * ( 11.0 - 5.0 ) ** 2 / 4 + 9 =>

5 * ( [11.0 - 5.0] ) ** 2 / 4 + 9 => 5 * 6.0 ** 2 / 4 + 9 =>

5 * 6.0 ** { 2 } / 4 + 9 => 5 * 6.0 ** 2.0 / 4 + 9 =>

5 * [ 6.0 ** 2.0 ] / 4 + 9 => 5 * 36.0 / 4 + 9 =>

{ 5} * 36.0 / 4 + 9 => 5.0 * 36.0 / 4 + 9 =>

[5.0 * 36.0] / 4 + 9 => 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 Exercise: Writing a Program Let c be the temperature in degrees Celsius. Let f be the temperature in degrees Fahrenheit. Then:

9 f = c + 32 5 Write a Fortran 90 program that prompts the user and then inputs a temperature in degrees Celsius, calculates the temperature in degrees Fahrenheit, then outputs the temperature in degrees Fahrenheit.

The body of the program must not have any numeric literal con- stants; all constants must be declared using appropriate symbolic names.

Don’t worry about comments.

18