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