It must be made clear at the outset that a REAL variable is no more "real" than an INTEGER, at least not in the sense that the latter is, say, a figment of the imagination. Mathematically, the integers can be regarded as a subset of the reals, though this is not true in Modula-2, because the two are different types.

A Modula-2REALnumber is one that is expressed as a series of significant figures including a decimal point, and optionally followed by a scale factor (power of ten).

Figure 2.10 illustrates this.

The notation used for REALs is the standard or scientific one, with a slight change to make it more computer readable. Consider the following representations:

DecimalScientificModula-22000 2.000 x 10^3 2.000E+03 0.058 5.8 x 10^-2 5.8E-02 6.023 x 10^-23 6.023E-23

**NOTE**: For such simple exponents as in the first two examples, the numbers may also be entered for a Modula-2 program as 2000. and 0.058 respectively. That is, the scale factor indicator and digits after the decimal may not be always necessary, but the decimal point is. Note that one may not substitute a lower case *e* for *E* when writing literals in a program.

The operations and their precedence are the same for REALs as for INTEGERs and CARDINALs, except that REM, MOD and DIV are not defined and REAL division is indicated only with the / (slash).

firstReal := 5.0 / 3.0; Answer: 1.66666 secondReal := 7.5 + 1.1 * 2.0; Answer: 9.7

To output these answers to the screen, the appropriate *WriteReal* statement is imported as usual. One must import it from *SRealIO* (In non ISO standard versions, the library may be called *RealIO* or *RealInOut* or these items may simply be included in *InOut*.) As in the previous statements of this type, a number following the REAL to be printed specifies the size of the field of blanks in which it is to be right justified.

The following module is typical of many that can be written to do conversions or other computations using a well-defined formula and having a simple output. As its only purpose is to demonstrate output of reals, and few other new concepts are present, no detailed plan is provided.

Write a module to convert a 14 degree Fahrenheit temperature to Celsius units.

MODULEConvertToCelsius; (* by R. Sutcliffe *)FROMSTextIOIMPORTWriteLn, WriteString, WriteChar;FROMSRealIOIMPORT(* note separate import statements *) WriteReal;CONSTFahrenheit = 14.0; (* this can be changed *) conversion = 32.0; (* difference between zero points *) ratio = 5.0 / 9.0; (* ratio between Celsius and Fahrenheit *)VARCelsius :REAL;BEGINCelsius := ratio * (Fahrenheit - conversion); WriteReal (Fahrenheit, 12); WriteChar ('F'); WriteString (" degrees equals "); WriteReal (Celsius, 12); WriteChar ('C'); WriteString (" degrees.");ENDConvertToCelsius.

The output from this program module is as follows:

14.0000000000F degrees equals -10.000000000C degrees.

**NOTES**: 1. The number of significant figures and the maximum size of the exponent allowed depends on the computer system being used. Here, twelve figures have been printed. A typical size range for many small computers is about 10^{-308} < real < 10^{308}, and similarly for negative reals.

2. There are other ways to format real number output that will be considered later.

3. The type LONGREAL is also available, and this extends the above range considerably.

Write a module to compute the area and circumference of a circle from a given radius.

MODULECircleAreaCirc;FROMSTextIOIMPORTWriteLn, WriteString;FROMSRealIOIMPORTWriteReal;FROMRealMathIMPORTpi;CONSTtwopi = 2.0 * pi; (* note the real constant expression *)VARarea, circumference, radius :REAL;BEGINradius := 4.0; (* calculate area and circumference *) area := pi * radius * radius; circumference := twopi * radius; (* inform the user *) WriteString ("A circle of radius "); WriteReal (radius, 0); (* spaces provided in the string parts *) WriteString (" units has a circumference of "); WriteLn; WriteReal (circumference, 0); WriteString (" units"); WriteString (" and an area of "); WriteReal (area, 0); WriteString (" square units.");ENDCircleAreaCirc.

The output from this program module is as follows:

A circle of radius 4.0000000 units has a circumference of 2.5132740E+1 units and an area of 5.0265480E+1 square units.

Sometimes a programmer wishes to print out real numbers, say to represent things like wages and bank balances in decimal or *fixed* form. At other times, the preference is for scientific or *floating point* notation. At still other times, engineering notation (in which the powers of ten are always multiples of three) is desired.

Fixed Floating Engineering 21421.5 2.14215E+4 21.4215E+3

Sometimes the number of significant figure needs to be specified. At other times it is the number of figures after the decimal that is of importance. For instance, when printing money values such as $15.34, fixed notation with two decimal places is necessary.

In ISO standard Modula-2 the library *SRealIO* has three additional procedures besides *WriteReal* for writing out real numbers.

WriteFloat (real, sigFigs, width);

writes out the specified *real* in floating point form with leading spaces if required to make the total space taken equal to *width* characters. One leading space is used if the width is zero. (This is the same behaviour as the *width* parameter for *WriteCard* and *WriteInt*.) If the value of *sigFigs* is greater than zero, it specifies the number of significant figures in the result. If the user of this procedure specifies zero figures, the particular implementation is free to define the outcome, and the manuals will have to be consulted. A sign is written only for negative values, and the exponent part is only written if it is not zero. No decimal point is included if there are no figures after it to print. The code

WriteFloat (pi, 4, 0); WriteLn; WriteFloat (1000.0 * pi, 4, 10); WriteLn; WriteFloat (10000.0 * pi, 6, 10); WriteLn; WriteFloat (pi/10000.0, 2, 10);

produces the output

3.142 3.142E+03 3.14159E+04 3.1E-04

WriteEng (real, sigFigs, width);

writes out the specified *real* in engineering form (exponents are multiples of three) with leading spaces if required to make the total space taken equal to *width* characters. The rest of the behaviour of *WriteEng* is the same as that of *WriteFloat*. The code

WriteEng (pi, 4, 0); WriteLn; WriteEng (1000.0 * pi, 4, 10); WriteLn; WriteEng (10000.0 * pi, 6, 10); WriteLn; WriteEng (pi/10000.0, 2, 10);

produces the output

3.142 3.142E+3 31.4159E+3 310E-6

WriteFixed (real, place, width);

writes out the specified *real* in fixed point form (ordinary decimal form) and rounded off to *place* figures after the decimal, with leading spaces if required to make the total space taken equal to *width* characters. The rest of the behaviour of *WriteFixed* is the same as that of *WriteFloat*. The code

WriteFixed (pi, 4, 0); WriteLn; WriteFixed (1000.0 * pi, 4, 10); WriteLn; WriteFixed (10000.0 * pi, 6, 10); WriteLn; WriteFixed (pi/10000.0, 2, 10);

produces the output

3.1416 3141.5930 31415.930000 0.00

Notice that the last number is zero to three figures, so that is all that gets written.

Returning to the idea of printing currency values, the code

WriteChar("$"); WriteFixed(pi,2,5)

produces the output

$ 3.14

with one space before the leading digit because four of the five spaces are occupied.

WriteReal (real, width);

behaves like a call to *WriteFixed (real, place, width)*; if the number can fit in the width provided. The value of *place* is chosen to exactly fill the remaining field. If the width is insufficient, the call to *WriteReal * behaves like one to *WriteFloat (real, sigFigs, width)*; with a value of *sigFigs* at least one, limited to those that can be included in the given width along with the exponent and sign. The code

WriteReal (pi, 0); WriteLn; WriteReal (1000.0 * pi, 10); WriteLn; WriteReal (10000.0 * pi, 10); WriteLn; WriteReal (pi/10000.0, 10);

produces the output

3.1415927 3141.59270 31415.9270 3.1415E-04

This matter presented somewhat of a difficulty for early implementors of Modula-2, because no such flexibility was defined or even suggested by Wirth as part of the standard operating environment. Indeed, in some Modula-2 implementations, it may not be possible to achieve the goal of formatting reals in these ways without doing some very hard programming work.

In fact,*non-ISO* standard compliant versions of Modula-2 may provide something like:

WriteReal (real, width, n);

where *real* represents the value to be written, and the second number is the width of the space to write in as before. The meaning of the third number, in such versions may be either the number of significant figures of the real to print, or the number of decimal places of the real to print. The library location of the alternate *WriteReal* may vary in such versions. Moreover, some non-standard versions of *WriteReal* switch to scientific notation whenever a negative sign is placed in front of the third supplied number. Observe that the usual ordering of the second and third numbers in non-ISO versions is often the opposite to that in ISO standard packages.

**NOTES**: 1. The user documentation for the compiler package of a non-ISO standard implementation must be checked carefully to determine which version of the *WriteReal* procedure has been provided, and in what library it is located.

2. Where more than one *WriteReal* is available, a specific implementation may even give them different names and/or place them in different libraries.