SuivantBasNiv. sup.

6.1 Arithmetic Expressions 

An expression in its simplest form is just a single operand, such as a constant or variable. More complicated expressions combine various operands with operators, which specify the computations to be performed. For example:       RATE * HOURS + BONUS The rules of Fortran have been designed to resemble those of mathematics as far as possible, especially in determining the order in which the expression is evaluated. In this example the multiplication would always be carried out before the addition, not because if comes first, but because it has a higher precedence. When in doubt, or to over-ride the precedence rules, parentheses can be used:       (ROOM + DINNER) * 1.15

Sub-expressions enclosed in parentheses are always evaluated first; they can be nested to any reasonable depth. If in doubt, there is no harm in adding parentheses to determine the order of evaluation or to make a complicated expression easier to understand.

Arithmetic expressions can contain any of the five arithmetical operators  +  -  *  /  ** . The double asterisk represents exponentiation, i.e. raising a number to a power. Thus the mathematical expression:

(1+ RAT E/100)years

could be represented in Fortran as:       (1.0 + RATE/100.0)**YEARS  (note the explicit decimal points in the constants to make them real values).

Arithmetic expressions can involve operands of different data types: the data type of the result is determined by some simple rules explained below.

General Rules 

Arithmetic expressions can contain arithmetic operands, arithmetic operators, and parentheses. There must always be at least one operand. The operands can belong to any of the four arithmetic data types (integer, real, double precision, or complex); the result also has an arithmetic data type. Operands can be any of the following:

The rules for forming more complicated arithmetic expressions are as follows. An arithmetic expression can have any of the following forms:
operand
+operand
-operand
arithmetic-expression   arith-op   operand
where the arith-op can be any of these operators:
+addition
- subtraction
* multiplication
/ division
**exponentiation
The effect of these rules is that an expression consists of a string of operands separated by operators and, optionally, a plus or minus at the start. A leading plus sign has no effect; a leading minus sign negates the value of the expression.

All literal arithmetical constants used in expressions must be unsigned: this is to prevent the use of two consecutive operators which is confusing and possibly ambiguous:       4 / -3.0**-1              (illegal). The way around this is to use parentheses, for example:       4 / (-3.0)**(-1) which makes the order of evaluation explicit. The order of evaluation of an expression is:

  1.  sub-expressions in parentheses
  2.  function references
  3.  exponentiation, i.e. raising to a power
  4.  multiplication and division
  5.  addition, subtraction, or negation.
Within each of these groups evaluation proceeds from left to right, except that exponentiations are evaluated from right to left. Thus: A / B / C is equivalent to (A / B) / C whereas X ** Y ** Z is equivalent to X ** (Y ** Z).

An expression does not have to be evaluated fully if its value can be determined otherwise: for example the result of:       X * FUNC(G) can be determined without calling the function FUNC if X happens to be zero. This will not cause problems if you only use functions that have no side effects.

Data Type Conversions 

If an operator has two operands of the same data type then the result has the same type. If the operands have different data types then an implicit type conversion is applied to one of them to bring it to the type of the other. These conversions always go in the direction which minimises loss of information: integer ===> real ===> complex or double precision

Since there is no way of converting a complex number to double precision type, or vice-versa, without losing significant information, both these conversions are prohibited: an operator cannot have one complex operand and one of double precision type. All other combinations are permitted. These implicit type conversions have the same result as if the appropriate intrinsic function (REAL, DBLE, or CMPLX) had been used. These are described in detail below. Note that the data type of any operation just depends on the two operands involved; the rest of the expression has no influence on it whatever.

Exponentiation is an exception to the type conversion rule: when the exponent is an integer it does not have to be converted to the type of the other operand and the result is evaluated as if by repeated multiplication. But if the exponent has any other data type the calculation is performed by implicit use of the LOG and EXP functions, thus: 2.0**3 ===> 2.0 * 2.0 * 2.0 ===> 8.0 2.0**3.0 ===> EXP(3.0 * LOG(2.0)) ===> 8.0

The first result will, of course, be computed more rapidly and accurately than the second. If the exponent has a negative value the result is simply the reciprocal of the corresponding positive power, thus: 2.0**(-3) ===> 1.0/2.0**3 ===> 1.0/8.0 ===> 0.125

Note that conversion from real to double precision cannot produce any information not present originally. Thus with a real variable R and a double precision variable D:
        R = 1.0 / 3.0
        D = R
D may end up with a value such as 0.3333333432674408... which is no closer to the value of one third than R was originally.

Integer Division 

Integer division always produces a result which is another integer value: any fractional part is truncated, i.e. rounded towards zero. This makes it especially important to provide a decimal point at the end of a real constant even if the fractional part is zero. For example: 8 / 3 ===> 2 -8 / 3 ===> -2 2**(-3) ===> 1/(2**3) ===> 1/8 ===> 0

The combination of the two preceding rules may have unexpected effects, for example: (-2)**3 ===> -2 * -2 * -2 ===> -8 whereas (-2)**3.0 is an invalid expression as the computer would try to evaluate the logarithm of -2.0, which does not exist. Similarly, the expression: 3 / 4 * 5.0 ===> REAL(3/4) * 5.0 ===> 0.0 whereas 5.0 * 3 / 4 ===> 15.0 / REAL(4) ===> 3.75

Restrictions 

Certain arithmetical operations are prohibited because their results are not mathematically defined. For example dividing by zero, raising a negative value to a real power, and raising zero to a negative power. The Fortran Standard does not specify exactly what is to happen if one of these errors occurs: most systems issue an error message and abort the program.

Errors can also occur because numbers are stored on a computer with finite range and precision. The results of adding or multiplying two very large numbers may be outside the number range: this is called overflow. A similar effect on very large negative integers is called underflow. Most systems will issue a warning message for overflow or underflow, and may abort the program, but some processors cannot detect errors of this sort involving integer arithmetic.

Every operand (variable, array element, or function reference) used in an expression must have a defined value at the time the expression is evaluated. Note that variables and arrays are initially undefined unless a suitable DATA statement is used. Expressions must not include references to any external functions with side effects on other operands of the expression: see section 9.3 for more details.

Arithmetic Constant Expressions 

Arithmetic constant expressions can be used in PARAMETER statements and to specify implied-DO parameters in DATA statements. All the operands in a constant expression must be literal constants or previously defined named constants. Variables, array elements, and function references are all prohibited. Exponentiation is only allowed if the number is raised to an integer power.

The same rules apply to integer constant expressions but in addition the operands must all be integer constants: such expressions can be used to specify array bounds in type, COMMON, and DIMENSION statements, and to specify string lengths in CHARACTER statements.

Bit-wise Logical Operations on Integers 

When Fortran programs communicate directly with digital hardware it may be necessary to carry out bit-wise logical operations on bit-patterns. Standard Fortran does not provide any direct way of doing this, since logical variables essentially only store one bit of information and integer variables can only be used for arithmetic. Many systems provide, as an extension, intrinsic functions to perform bit-wise operations on integers. The function names vary: typically they are IAND, IOR, ISHIFT. A few systems provide allow the normal logical operators such as .AND. and .OR. to be used with integer arguments: this is a much more radical extension and much less satisfactory, not only because it reduces portability, but also reduces the ability of the compiler to detect errors in normal arithmetic expressions.

Many systems also provide format descriptors to transfer integers using octal and hexadecimal number bases: these are also non-standard.

Guidelines 

Expressions with mixed data types should be examined carefully to ensure that the type-conversion rules have the desired effect. It does no harm to use the type conversion functions explicitly and it may make the working clearer.

Particular care is needed with the data types of literal constants. It is bad practice to use an integer constant where you really need a real constant. Although this will work in most expressions it is a serious mistake to use the wrong form of constant in the argument list of a procedure.

Long and complicated expressions which spread over several lines can be rather trying to read offer more scope for programming errors. Sometimes it is better to split the computation into several shorter equations at the expense of one or two temporary variables.

It is often tempting to try to write programs that are as efficient as possible. With modern compilers there is little point in trying to rearrange expressions to optimise speed. One of the few exceptions is that if an intrinsic function is provided it is always best to use it; thus SQRT(X) is likely to be faster and more accurate than X**0.5.

You may find that your system actually sets the whole of memory to zero initially, except for items defined with DATA statements, but it is very bad programming practice to rely on this.

SuivantHautNiv. sup.