2.10 Type Compatibility and REAL

In section 2.7, it was observed that CARDINAL and INTEGER are assignment compatible, even if they are not expression compatible. Assignment compatibility is in this case a small concession to the normally strict rule against mixing types--these two are used in similar ways. It can be achieved easily because most computers also store values of these two types in similar ways. However, both the use and the storage of REAL values is quite different than for either INTEGER or CARDINAL values. Therefore one cannot in Modula-2 write either of

firstReal := -7;
secondReal := firstReal + card;

where firstReal and secondReal are REAL and card is CARDINAL. That is:

In Modula-2 the type REAL is neither assignment compatible nor expression compatible with CARDINAL or INTEGER.

However, there is a way to convert numbers to and from REAL representation. If re is of type REAL and ordnum is of type INTEGER or CARDINAL, then

re := FLOAT (ordnum)

will safely convert ordnum to a REAL, and assign the resulting value to re. Likewise,

card := TRUNC (re)

will safely convert the whole number part of re to a CARDINAL and assign the resulting value to the variable card. Furthermore,

ordnum := INT (re)

will safely convert the whole number part of re to an INTEGER and assign the resulting value to the variable ordnum.

NOTES: 1. These two are examples of what are called functions, or, more properly in Modula-2 function procedures.

2. The above definitions hold for ISO standard Modula-2. In some older implementations of Modula-2 the FLOAT may only work on one of the types INTEGER or CARDINAL and TRUNC conversions may produce an INTEGER rather than a CARDINAL. There may not even be an INT function procedure.

3. These two operations allow the creation of mixed expressions. Naturally, FLOAT and TRUNC have the precedence of parentheses.

4. TRUNC does not round off to the nearest cardinal, it "hacks off" the decimal part instead.


Assume re is REAL, int is INTEGER, and card is CARDINAL

re := 2.6 + FLOAT (5);		Answer:  7.6
int := 26 - 2 * INT (re);	Answer:   12
card := 26 - TRUNC (re * 2);	Answer:   11
int := INT (-4.75) - 6;		Answer:  -10

2.10.1 Additional Conversion Functionality

Many computers have more than one format for storing real numbers. Typically, there is one for reals with a somewhat limited range of significant figures and exponent, and one or more additional types with a greater range for both. Because of this, ISO standard Modula-2 provides for a second real type called LONGREAL. The precision and the exponent range for this type must be at least as great as for the type REAL. Thus, if only one real type is available in the underlying machine, the two real types would essentially be the same. However, since this is implementation defined (and somewhat exceptional), the compatibility rule is:

The Modula-2 type REAL and the Modula-2 type LONGREAL are not compatible.

Thus, besides the conversion functions above, ISO standard Modula-2 adds LFLOAT to convert to the type LONGREAL. Since REAL values need conversion to LONGREAL as well, LFLOAT takes any of CARDINAL, INTEGER, or REAL. In addition, INT, TRUNC, and FLOAT can take any numeric type that need to be converted to INTEGER, CARDINAL, or REAL, respectively. Note that this behaviour cannot be counted on in non-ISO standard versions.


Assume int is an INTEGER, card is a CARDINAL, re is a REAL and lre is a LONGREAL.

int := INT (-3.5);			Answer: -3  (works like TRUNC)
lre := LFLOAT (2.7);		Answer: 2.7 (* but stored as a LONGREAL *)
lre := LFLOAT (-3);		Answer: -3.0 (* stored as a LONGREAL *)
re := FLOAT (-3);			Answer: -3.0 (* stored as a REAL *)
re := FLOAT (INT (5.1));	Answer: 5.0
card := TRUNC (-3.5);		Answer: error; presumably need to use INT
int := INT (lre);			Answer: be careful; could overflow!

NOTES: 1. Nonstandard versions that add such types as LONGINT and LONGCARD may have additional conversion functions.

2. Many nonstandard versions add the conversion function CARD, to convert to CARDINAL, instead of or in addition to TRUNC.

3. In the ISO standard, TRUNC, INT, FLOAT, and LFLOAT are simply short notation for the corresponding use of VAL (mentioned briefly in section 2.7). That is,

INT (r) means VAL (INTEGER, r),

TRUNC (r) means VAL (CARDINAL, r),

FLOAT (i) means VAL (REAL, i), and

LFLOAT (i) means VAL (LONGREAL, i).

The Modula-2 function procedure VAL(newType,item) safely converts the value stored in item into a corresponding value of the type newType.