home *** CD-ROM | disk | FTP | other *** search
-
-
- Chapter 6
- ADDITIONAL SCALAR TYPES
-
-
- OUR OWN TYPES
- _________________________________________________________________
-
- Most of the example programs in this tutorial have used the
- predefined type INTEGER for illustrating various concepts, and it
- is an excellent choice due to its versatility. There are other
- types available because they are part of the Ada definition, and
- we can define our own types for special purposes. This chapter
- will illustrate to you some of the reasons for doing so.
-
- A complete description of types will be given in the next chapter
- but first we will learn how to use some of them. We are caught in
- a dilemma like the proverbial, "which came first, the chicken or
- the egg?", and must select which to define first. We have chosen
- to illustrate usage in this chapter, and then give the details of
- type definition in the next chapter.
-
-
-
- A FEW integer CLASS TYPES
- _________________________________________________________________
-
- Examine the file named ALLINT.ADA for some ================
- examples of how and why we can use our own type ALLINT.ADA
- definitions. The three types illustrated in ================
- lines 10 through 12 are available with all Ada
- compilers because they are so versatile and
- useful, and because they are required by the Ada programming
- language. As we have said before, the type INTEGER defines a
- variable that can have any whole value between -32768 to 32767 on
- most microcomputers and some minicomputers too. It should be
- pointed out that most minicomputers use a much larger range as
- standard. The type NATURAL defines a variable from 0 to 32767, and
- the type POSITIVE covers the range from 1 to 32767 on most
- microcomputers.
-
- Consider the word "most" in the last paragraph, and think about the
- problems you could have if you wrote a program that depended on a
- particular variable covering the listed range, and tried to move
- the program to a different machine which used a different range.
- You could be faced with a large rewrite problem in order to get
- the program to work on the new computer.
-
-
-
- HOW CAN WE HELP SOLVE PORTABILITY PROBLEMS
- _________________________________________________________________
-
- Suppose we defined our type to cover a certain range, such as
- illustrated in line 14 of the example program, and moved the
-
- Page 6-1
-
- Chapter 6 - Additional Scalar Types
-
- program to another computer. According to the definition of Ada,
- the new compiler would be obligated to create a type for us that
- would cover the given range, or give us a compile time error
- telling us that the hardware simply could not support the defined
- range. In this case, due to the rather small range requested, any
- meaningful compiler and machine combination would be able to cover
- the defined range, and we would have a program that would run in
- spite of differences in the way the standard types were defined.
- Good programming practice, especially if the source code may need
- to be moved to other computers, would define all ranges explicitly
- and avoid the implementation defined limits built into the
- compiler.
-
- Two new types are defined in lines 14 and 15, and the program uses
- some new attributes to illustrate the new types. In lines 24 and
- 27, we use two attributes which we have used before, but in lines
- 31 and 34, we use two new attributes. In order for the system to
- create a type which covers a range of -1000 to 24000, it must use
- a structure with enough binary bits to cover the given range. The
- range is not composed of binary limits so the system will have to
- define enough bits to cover this range and a little more. It will
- probably define some number of 8-bit bytes and the range covered
- by the full pattern, as defined, is called the base range. The two
- new attributes give the limits of the base selected by the system.
- The base limits will probably be -32768 to 32767 if you are using
- a microcomputer, as you will see when you execute the program.
-
-
-
- DO YOU HAVE A SMART COMPILER?
- _________________________________________________________________
-
- The type illustrated here named MY_SHORT has defined limits of -12
- and 127, a relatively small range. It is small enough that it can
- fit into a base range of -128 to 127, which could be stored in a
- single 8-bit byte. If your compiler is smart enough to realize
- that, it could use a single 8-bit byte to store every variable of
- this type, and if you had a lot of these to store, it would save
- you a lot of memory. You will probably find however, that most
- compilers will simply use the full INTEGER range for the base type
- of even this small number.
-
- Four attributes of two different types are displayed on the monitor
- for your information. You can see from the results of running this
- program exactly how your compiler stores these two types.
-
-
-
- THE in AND not in OPERATORS
- _________________________________________________________________
-
- We have a new operator to learn about now, the in operator
- illustrated in line 48. If the variable Index, which has a current
- value of 345 due to initialization, is within the defined range of
-
- Page 6-2
-
- Chapter 6 - Additional Scalar Types
-
- the subtype MY_SUBTYPE, a BOOLEAN type TRUE will be returned,
- otherwise a BOOLEAN type FALSE is returned. This result can be
- assigned to a BOOLEAN variable or used for a boolean decision as
- shown. In this case, the value of Index is not in the range of
- MY_SUBTYPE so a FALSE is returned and the message will not be
- output. Another operation is illustrated in line 53 which is the
- not in operation, and should be self explanatory. You should be
- able to see that the message in line 53 will be displayed. The in
- and not in operators are further illustrated in lines 56 and 60
- where an explicit range is used for the test range.
-
- Be sure to compile and run this program and observe the output.
- Here is a chance for you to see if you have a smart compiler.
-
-
-
- THE ENUMERATED TYPE
- _________________________________________________________________
-
- Examine the program named ENUM.ADA for our first ================
- look at an enumerated type and how it is used in ENUM.ADA
- a program. Line 7 is the first definition of an ================
- enumerated type, and uses the reserved words
- type and is as shown. The type name is given
- between the two reserved words and the values which a variable of
- this type is allowed to have assigned to it are given as a list
- within parentheses. The values actually represent numerical values
- from 0 up to that value required for the largest value, in this
- case 6, since the numbering will be assigned from 0 to 6. In line
- 20, the variable named Day_Of_Week is declared to be of type DAY,
- so it can be assigned any of the 7 values listed for the type DAY,
- and no others. We could assign the values 0, 1, 2,.. 6 to
- represent the 7 days of the week and use the numerical values
- within the program, but by using the enumerated type, we can refer
- to Sunday as SUN, Monday as MON, etc., making the program much
- clearer and easy to follow.
-
- Enumerated types are always locally defined because there are no
- predefined enumerated types in the Ada language. There is one
- exception to this, because the BOOLEAN type is an enumerated type
- with two possible values, but it has some special properties
- available with no other enumerated variables. These will be
- discussed using the next example program.
-
- Jumping ahead to the executable code in the current example
- program, we illustrate assignment in line 28, where we assign the
- value of WED to the variable Day_Of_Week. Lines 29 and 30
- illustrate the FIRST and LAST attributes which we have seen before
- for integer type variables. Just as -32768 is the lowest possible
- value that can be assigned to an INTEGER type variable, MON is the
- lowest, and hence the first, value that can be assigned to a
- variable of type DAY.
-
-
-
- Page 6-3
-
- Chapter 6 - Additional Scalar Types
-
- TWO NEW ATTRIBUTES
- _________________________________________________________________
-
- Lines 31 and 32 illustrate the attributes PRED, which means the
- predecessor, and SUCC, which means the successor. PRED returns the
- value of the predecessor of the present value of the variable used
- as an argument. Since the variable Day_Of_Week was assigned the
- value of SUN in line 30, and the day just prior to SUN is SAT, SAT
- is assigned to the variable Day_Of_Week in line 31. It is an error
- to attempt to take the PRED of a variable which contains the first
- value in the available list, and will result in raising the
- exception Range_Error. Likewise, an attempt to take the SUCC of
- any variable that is at its maximum value will result in the
- exception Range_Error being raised. Exceptions will be covered in
- detail later in this tutorial. At this time simply remember that
- an exception refers to an exceptional condition or an error.
-
-
-
- WHAT IS A SUBTYPE OF AN ENUMERATED TYPE?
- _________________________________________________________________
-
- In lines 8 and 9, we define two subtypes of the type DAY which will
- have all the characteristics of type DAY except for a more
- restricted range. A variable that is declared to be of type
- PLAY_DAY can be assigned either of two values, SAT or SUN. SAT
- will have a numerical value of 5, and SUN will have a numerical
- value of 6, both of these being inherited from the parent type,
- DAY. Thus in line 32, we use the attribute FIRST to get the first
- day of type PLAY_DAY, which will be SAT, then use the attribute
- SUCC to get the successor of that value, which will be SUN. Notice
- how the attributes can be combined to obtain the needed
- information. A subtype is assignment compatible with its parent
- type. We will discuss subtypes in greater detail in the next
- chapter of this tutorial.
-
-
-
- NOW FOR THE POS AND VAL ATTRIBUTES
- _________________________________________________________________
-
- The POS attribute will return a value of type universal_integer,
- the value representing the position of the enumerated value within
- the parentheses as shown in lines 33 and 34. The VAL attribute
- will return the enumerated value of the numerical value included
- in the parentheses. Notice that if the type DAY in line 35 were
- changed to PLAY_DAY, an error would be returned, since that is an
- illegal enumerated value for that type. The error would be
- returned by raising the exception Range_Error.
-
-
-
-
-
-
- Page 6-4
-
- Chapter 6 - Additional Scalar Types
-
- WHAT ABOUT ENUMERATED ASSIGNMENTS?
- _________________________________________________________________
-
- The value of Happy_Day can be assigned to Day_Of_Week at any time
- because they are both of the same type, and any value that can be
- legally assigned to Happy_Day can also be assigned to Day_Of_Week.
- Day_Of_Week cannot always be assigned to Happy_Day however, because
- Day_Of_Week is permitted to contain some values which are not legal
- to assign to Happy_Day. This would illustrate that some care must
- be exercised when using the enumerated type, but if used properly,
- it can help in program debugging by the use of the strong
- type-checking defined into the Ada language.
-
-
-
- USING ENUMERATED TYPES FOR CONTROL
- _________________________________________________________________
-
- The loop in lines 37 through 40 covers exactly the range covered
- by the subtype WORK_DAY, so we can use it in the range part of the
- definition of the loop. When you run this program, you will see
- that the loop will be executed exactly five times.
-
- Lines 42 through 51 contain two relational checks on the variable
- Today to illustrate that the enumerated type variable can be used
- in a BOOLEAN expression. All of the boolean operators are
- available, which includes the following list, and no others;
-
- = equality
- /= inequality
- > greater than
- >= greater than or equal to
- < less than
- <= less than or equal to
-
- No mathematical operations are available with enumerated type
- variables. Assignments are available as illustrated in the present
- example program.
-
-
-
- WHAT IS QUALIFICATION?
- _________________________________________________________________
-
- In lines 53 and 54, we assign the same value to two different
- enumerated type variables. At least it seems to be the same value.
- In actuality, they are two different values with the same name,
- namely SUN. Because Ada does such strong type checking, it is
- smart enough to realize that they are actually two different
- constants and it will select the one that it needs for each
- statement based on the type of the variable to which it will be
- assigned.
-
-
-
- Page 6-5
-
- Chapter 6 - Additional Scalar Types
-
- Lines 56 and 57 make the identical assignments by qualifying which
- value you are interested in, but in this case, the qualifications
- are unnecessary. There could be a case when you would need to tell
- the system which value of SUN you are interested in. Qualification
- uses the type followed by a "tick", or apostrophe, prior to the
- enumeration value.
-
-
-
- OUTPUTTING ENUMERATED VARIABLES
- _________________________________________________________________
-
- The statements in lines 59 and 60 output the current value of the
- variable Today, and the predecessor of the current value. Finally,
- the same values are output for the variable Big_Sphere, and when
- you run the program, you will see that the same value is output for
- the first value in each line, but the second values differ for the
- two variables. Note the four extra lines given in program lines
- 14 through 18. These are used to tell the system how to output
- enumerated variables, and we will cover the essentials of how this
- works very soon.
-
- The in and not in operators which we studied in the last program
- are available for use with the enumerated type variable. In fact,
- they are available with all discrete types. Be sure to compile and
- run this program and after studying the results, see if you can
- modify the program to output additional enumerated values.
-
-
-
- THE BOOLEAN VARIABLE
- _________________________________________________________________
-
- The program named BOOLVARS.ADA is an ================
- illustration of how to use the BOOLEAN variable, BOOLVARS.ADA
- which is actually a special case of an ================
- enumerated variable. Every enumerated type must
- be defined by the user, before use, with the
- exception of the predefined BOOLEAN type. It is simply an
- enumerated type with two possible values, TRUE or FALSE. Since it
- is an enumerated type, all of the operations available with the
- enumerated type are available with the BOOLEAN type, including all
- six of the relational operators, the assignment operator, the
- attributes, and no mathematical operators.
-
-
-
- THE LOGICAL OPERATORS
- _________________________________________________________________
-
- The BOOLEAN type has some of its own unique operators that are
- available with no other types, the logical operators. The logical
- operators were defined earlier, but are repeated here as a complete
- list.
-
- Page 6-6
-
- Chapter 6 - Additional Scalar Types
-
- and logical and operation
- or logical or operation
- xor exclusive or of two values
- not inversion of the value
- and then short circuit and operation
- or else short circuit or operation
-
- It should be pointed out that FALSE is of less numerical value than
- TRUE, by definition, and in actuality, the value of FALSE is 0, and
- the value of TRUE is 1.
- The program illustrates how to output BOOLEAN values in lines 29
- and 30, after the package instantiation in lines 7 and 8. Notice
- that the Enumeration_IO library is used for BOOLEAN output
- illustrating again that BOOLEAN is a special case of the enumerated
- type.
-
- Be sure to compile and execute this program to see that it really
- does compile as stated. Someday, you will need the ability to
- display the BOOLEAN results as is done in this program.
-
-
-
- SOME USELESS ATTRIBUTES OF INTEGER TYPES
- _________________________________________________________________
-
- It may seem silly to illustrate some useless ===============
- attributes but the program named INCRINT.ADA INCRINT.ADA
- does that very thing. The POS attribute of an ===============
- integer variable is defined as being the number
- itself, and the VAL is also the number. The
- SUCC of an integer variable is the next number, and the PRED is the
- predecessor. These last two attributes could be useful for
- incrementing or decrementing a variable in a program, but good
- programming practice would forbid such a use of these attributes.
- You should use the very clear and easy to understand method of
- adding one to the value and assigning the result back to the
- variable, as illustrated in line 17 of the program.
-
- Even though these are really useless at this point in time, the
- fact that this can be done will be very useful when we get to the
- study of generics later in this tutorial.
-
- Compile and run this program, adding some output to gain some of
- your own programming experience.
-
-
- FLOATING POINT VARIABLES
- _________________________________________________________________
-
- Examine the program named FLOATVAR.ADA for ================
- examples of nearly all operations possible with FLOATVAR.ADA
- floating point numbers. ================
-
-
-
- Page 6-7
-
- Chapter 6 - Additional Scalar Types
-
- We begin, in lines 7 and 8, by defining two constants, the second
- being defined in terms of the first. Remember that any thing used
- in an Ada program must be previously defined, and you will know all
- of the rules for defining a value in terms of some other value.
- The two constants are of type universal_real, so they can be used
- with any of the various real types we will encounter in this
- program. We declare a variable named R in line 10 of type FLOAT,
- which is defined by the compiler writer, then two new types of
- floating point numbers, and we finally declare six variables of
- various types.
-
- Two additional floating point types, SHORT_FLOAT and LONG_FLOAT are
- defined as optional by the LRM and may be available with your
- compiler. You can find out by checking the documentation supplied
- with your compiler or by declaring variables of those types to see
- if the compiler will accept the declarations. If they do exist,
- you can determine their limits by using attributes as defined
- below.
-
-
- HOW TO DECLARE A NEW FLOATING POINT TYPE
- _________________________________________________________________
-
- The reserved word digits used in line 12 tells the compiler that
- you don't care how many bytes of storage it uses to define the
- number, but it must store at least 7 significant digits for every
- variable of type MY_FLOAT. Line 13 requests a minimum of 15
- significant digits for every variable of type MY_LONG_FLOAT. Line
- 10, on the other hand, only requires that it be a floating point
- number, and the compiler writer has the option of using as many
- significant digits as he desires to implement variables of this
- type. If you wrote a program that ran well with one compiler, it
- may not run properly with a different compiler, either because the
- new one did not use enough significant digits, or because the new
- one used far more causing your program to run out of storage space
- or run too slowly. The forms in lines 12 and 13 are therefore
- preferred for portability purposes. More will be said about
- declaring floating point types in the next chapter of this
- tutorial.
-
-
- FLOATING POINT LITERALS
- _________________________________________________________________
-
- The distinguishing characteristic that defines a floating point
- number is the use of a decimal point. Ada requires at least one
- digit before and after the decimal point, although either or both
- may be zeros. Single embedded underlines are allowed to improve
- readability, but cannot be adjacent to the decimal point. The
- underlines are ignored by the compiler, and have no significance.
- Any radix from 2 through 16 may be used by first giving the radix,
- then enclosing the number in pound (#) characters. The base 10 is
- the default and need not be specified. Exponential notation can
- be used, the exponent being to the same base as that indicated by
-
- Page 6-8
-
- Chapter 6 - Additional Scalar Types
-
- the radix. A binary floating point literal is illustrated in line
- 31 of the program and you can see that the radix is similar to that
- used for integer class literals.
-
-
- FLOATING POINT MATHEMATICAL OPERATORS
- _________________________________________________________________
-
- Lines 29 through 35 illustrate the mathematical operators available
- with floating point variables and should be self explanatory with
- the exception of the exponential operator. This can use only an
- integer type of exponent but it can be either positive or negative.
- Of course, zero is also permissible.
-
- All six logical comparisons are available with floating point
- variables as illustrated in lines 38 through 43. The next two
- lines, 45 and 46, illustrate some multiple mathematical operations.
-
- As with all variables, the types must agree within all mathematical
- and logical operations and the result must be assigned to the right
- type of variable, or a type error will be generated at compile
- time. In line 46, the variable Area must be transformed in type
- prior to being assigned to Cover since they are of different types.
- The entire statement will be evaluated as of type MY_LONG_FLOAT,
- since that will be the final result. The constant 27.3, and the
- constant PI, will be transformed automatically from universal_real
- to MY_LONG_FLOAT prior to the multiplications.
-
-
-
- NOW TO OUTPUT SOME FLOATING POINT VALUES
- _________________________________________________________________
-
- In lines 24 and 25 we instantiate a copy of the Float_IO package
- for use with the type MY_FLOAT and use it in lines 49 through 55.
- The variable Area will be output in a default exponential notation
- in line 49, but with 5 digits prior to the decimal point in line
- 50. Line 54 adds an additional 5, which will cause 5 digits to be
- output following the decimal point, and the fourth field, in this
- case a zero, causes the output to be written with a zero exponent,
- or no exponential notation.
-
-
-
- FLOATING POINT ATTRIBUTES
- _________________________________________________________________
-
- Floating point variables and types are no different from the scalar
- types concerning attributes available for your use, except that
- there are different attributes available. Lines 58 through 72
- illustrate the use of some of the available attributes. The
- attribute named DIGITS, gives the number of significant digits
- available with the specific type, and the return is a
- universal_integer type.
-
- Page 6-9
-
- Chapter 6 - Additional Scalar Types
-
-
- The attributes named SMALL and LARGE give the smallest and largest
- numbers available with the corresponding type, and the attributes
- named FIRST and LAST combined with the BASE attribute as shown in
- lines 68 and 71, define the extreme values as used by the
- underlying base type of the actual user's type. All four of these
- attributes return a value of the type universal_real, and are
- displayed on the monitor for your information. Note that there are
- other attributes available with the floating point type, but only
- these will be elaborated upon at this time.
-
- See appendix A of the LRM for additional information on attributes.
- This appendix lists all of the attributes available with an Ada
- system.
-
- Compile and run this program and observe the output. The actual
- output is the clearest description of the Put procedure when used
- with floating point numbers. Study the result of the attribute
- outputs before continuing on to the next example program.
-
-
-
- FIXED POINT VARIABLES
- _________________________________________________________________
-
- Fixed point variables are a relatively new ===============
- concept and may be a bit confusing, but the file FIXED.ADA
- named FIXED.ADA will illustrate the use of a few ===============
- fixed point variables. Line 9 defines a fixed
- point type as having a range of -40.0 to 120.0,
- and a delta of 0.1 which means that a variable of this number can
- only have a value that is accurate to one digit after the decimal
- point. There are therefore a fixed number of digits before and
- after the decimal point, hence the name of this type of variable.
-
-
- A fixed point number will always be exact since it is defined that
- way. There can never be a gradual accumulation of error with a
- fixed point variable. In order to completely understand the fixed
- point type, one would require a complete understanding of numerical
- analysis, which is beyond the scope of this tutorial. The program
- before you will illustrate how to use this type, but no attempt
- will be made to explain why it should be used.
-
- There are no predefined fixed point types, so it is up to the
- programmer to define every fixed point type needed, as illustrated
- in lines 9 and 10. The reserved word delta denotes a fixed point
- type and a range is required for every fixed point type. Lines 12
- and 13 are used to declare a few variables for use in the program,
- then lines 17 through 20 instantiate the package Fixed_IO for use
- with our two fixed point types.
-
-
-
-
- Page 6-10
-
- Chapter 6 - Additional Scalar Types
-
- HOW DO WE USE FIXED POINT TYPES?
- _________________________________________________________________
-
- Output of a fixed point type uses the same format as that defined
- for floating point data as shown in line 27. When we come to
- arithmetical operations, we find some funny rules which we will
- simply state, and make no attempt to justify. Variables of the
- same fixed point types can be added and subtracted freely, provided
- the results are within the defined range, just like floating point
- type variables. Multiplication by a constant of type
- universal_integer is permitted, resulting in the same fixed point
- type we started with. Multiplication of two fixed point variables
- results in an anonymous type which must be explicitly converted to
- some predefined type, as illustrated in lines 33 and 34. The only
- operator available with the fixed types is the abs operator.
-
- Many attributes are available with the fixed point type, some of
- which are illustrated in lines 46 through 61. The attributes named
- DELTA, SMALL, and LARGE, each return a value which is of type
- universal_real, and must be converted to the users fixed type, by
- a type conversion, before the result can be used in the program.
- Line 48 illustrates the conversion within the Put procedure call.
- Lines 51 and 54 illustrates the explicit conversion to a FLOAT
- type, but since the results are to be used as FLOAT variables, and
- the universal_real type can be used directly as a FLOAT type, the
- conversion is not actually required.
-
- Be sure to compile and run this program and observe the output to
- see if it conforms to what you think it should do based on the
- previous discussion. Note that your compiler may not generate
- identical output as that listed in the result of execution due to
- different compiler defaults.
-
-
-
- MIXING VARIOUS TYPES
- _________________________________________________________________
-
- Examine the program named MIXTYPES.ADA for ================
- examples of using various types together. It is MIXTYPES.ADA
- meant to be an illustration of how to combine ================
- some of the various types available in Ada.
- Many type transformations are illustrated in
- this program and should be easy for you to understand. Note
- especially, that the final result of lines 27, 28, and 29 will not
- necessarily be the same due to the rounding that takes place at
- different points in the calculations.
-
- Note that in Ada, conversion from real to integer always rounds
- rather than truncates. A value midway between the two integer
- values can go either way since it is not defined by the LRM but is
- left up to the implementor.
-
-
-
- Page 6-11
-
- Chapter 6 - Additional Scalar Types
-
- Compile and execute this program to assure yourself that it will
- compile correctly.
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Write a program to determine if LONG_INTEGER and SHORT_INTEGER
- types are available with your compiler. If they are
- available, use attributes to determine their characteristics.
-
- 2. Do the same thing as exercise 1 for the LONG_FLOAT and
- SHORT_FLOAT types.
-
- 3. Try to take the PRED of the first element of an enumerated
- variable to see what kind of a run-time error you get. Your
- compiler may be smart enough to warn you if you try to take
- it directly (i.e. - by using the first value in the
- parentheses), so you may need to assign a variable to the
- first value and take the PRED of the variable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 6-12