2-2 CONSTANTS
**************
(Thanks to Craig Burley for the excellent comments)
Types of constants
------------------
There are two types of FORTRAN constants:
1) Named constants, are declared with the PARAMETER
statement. Can be assigned a data type with the
ordinary data type declarations.
2) Unnamed constants, are directly used in the
source code, the data type is inferred by the
compiler from the constant's form.
Good programming practice requires using named constants as
much as possible (within reasonable limits).
Remember that a constant may be represented internally in several
ways according to its data type, e.g. different types of integers
(INTEGER*2, INTEGER), or floating-point numbers (REAL, DOUBLE
PRECISION, REAL*16). When you pass a constant to a procedure,
it's very important to have the compiler handle it with the
correct data type.
A "bad" example program:
PROGRAM CONST
CALL SUB(1.0)
END
SUBROUTINE SUB(X)
DOUBLE PRECISION X
WRITE (*,*) ' X= ', X
RETURN
END
The output of this program, will be most probably not the value
you expect (1.0).
Untyped integer constants
-------------------------
In every programming language, if you write an explicit integer constant,
e.g. 100, the compiler may have no way to decide which of the available
integer types is required (some FORTRAN compilers offer INTEGER*1,
INTEGER*2, INTEGER*4 and INTEGER*8 types).
If an untyped integer constant is contained in the range of more
than one of the available integer types, the compiler can't make an
unambiguous decision. It may choose the smallest of the available
types, or a default one (provided it is large enough).
Automatic type promotion (done by the compiler when computing an
arithmetical expression) doesn't solve the problem, on the contrary
it may create it.
Conversion to a too 'small' type may truncate the number, conversion
to a too 'large' type may also create problems, for example the
'too large' type may be:
1) passed to a procedure that expects a different integer type
2) processed in a wrong way by bit-manipulation operations,
or other manipulations of the internal representations
In such cases you may get wrong results.
+-----------------------------------------------------+
| Use PARAMETER statements, and type each constant. |
+-----------------------------------------------------+
Precision of floating-point constants
-------------------------------------
FORTRAN uses 'typed constants' - every constant has a data type.
FP constant type Produced if Example
================ ============================= =============
Single-precision No exponent is specified, 1.1
or is specified with an 'E' 0.11E+01
Double-precision Exponent specified with a 'D' 0.11D+001
Quad-precision Exponent specified with a 'Q' 0.11Q+0001
Two remarks:
1) Constants without an exponent part are single-precision
2) Quad-precision (REAL*16 on most machines) is Non-standard
Constants may be converted to internal representation at an earlier
stage of the compilation, and then be used with the same type promotion
rules as variables.
In the following code fragment the constant may be converted into a
REAL internal representation, and then converted to a DOUBLE PRECISION
internal representation:
DOUBLE PRECISION X
.......................
X = 47.500001
Assigning a single precision constant (a common error), to a double
precision variable may cause serious loss of precision, and lead to
erroneous results.
Some compilers automatically interpret a single precision constant
as a double precision one if it is assigned to a double variable,
some are said to count the digits and decide accordingly, however
you should not rely on such features.
Some people consider such 'correcting compilers' dangerous and
misleading by offering these re-interpreting features, even though
some users think they like them.
You can check your compiler with the following program
(Precision comparable to 32/64 bits is assumed):
PROGRAM CONSTS
C ------------------------------------------------------------------
REAL
* X4, Y4
C ------------------------------------------------------------------
DOUBLE PRECISION
* A8, B8, C8
C ------------------------------------------------------------------
PARAMETER(
* X4 = 0.4750001E+02,
* Y4 = 0.475E+02)
C ------------------------------------------------------------------
WRITE(*,*)
WRITE(*,*) ' DOUBLE PRECISION variable = REAL parameter '
WRITE(*,*) ' ========================================== '
A8 = X4
B8 = Y4
C8 = X4 - Y4
WRITE(*,*) ' A8 = ', A8
WRITE(*,*) ' B8 = ', B8
WRITE(*,*) ' C8 = ', C8
C ------------------------------------------------------------------
WRITE(*,*)
WRITE(*,*) ' DOUBLE PRECISION variable = REAL constant '
WRITE(*,*) ' ========================================= '
A8 = 0.4750001E+02
B8 = 0.475E+02
C8 = A8 - B8
WRITE(*,*) ' A8 = ', A8
WRITE(*,*) ' B8 = ', B8
WRITE(*,*) ' C8 = ', C8
C ------------------------------------------------------------------
WRITE(*,*)
WRITE(*,*) ' DOUBLE PRECISION variable = default constant '
WRITE(*,*) ' ============================================ '
A8 = 47.50001
B8 = 47.5
C8 = A8 - B8
WRITE(*,*) ' A8 = ', A8
WRITE(*,*) ' B8 = ', B8
WRITE(*,*) ' C8 = ', C8
C ------------------------------------------------------------------
WRITE(*,*)
END
+---------------------------------------------------------------+
| USE CONSTANTS OF THE SAME TYPE AS THE VARIABLES/EXPRESSIONS |
+---------------------------------------------------------------+
Using named constants modularly
-------------------------------
Named constants are declared in PARAMETER statements, and can have
values that are expressions involving previously defined constants.
Using intrinsic functions in such expressions is not standard
FORTRAN 77, but is supported by some compilers (and should be
supported by g77-0.6).
Using intrinsic functions in PARAMETER statements is not like
using them in the executable part of a program, the PARAMETER
expressions are computed by the compiler, not by the program
at run-time. Some compilers rejects these expressions, others
may die due to segmentation fault or such.
A small example:
INTEGER
* RECORD_SIZE,
* NUM_RECORDS,
* FILE_SIZE
C ------------------------------------------------------------------
PARAMETER(
* RECORD_SIZE = 80,
* NUM_RECORDS = 1000,
* FILE_SIZE = RECORD_SIZE * NUM_RECORDS)
C ------------------------------------------------------------------
Readability
-----------
You can use space characters inside constants to enhance readability,
for example:
PARAMETER(NMAX = 1 200 000)
You can't use spaces inside constants in F90 free form, which is
likely to be the _only_ form available someday.
Return to contents page