A fixed point type defines a set of values that are evenly spaced with a given absolute precision. In contrast, floating point values are all spaced according to a relative precision.
The absolute precision is given as the delta of the type. There are two kinds of fixed point types, ordinary and decimal.
For Ordinary Fixed Point types, the delta gives a hint to the compiler how to choose the small value if it is not specified: It can be any integer power of two not greater than delta. You may specify the small via an attribute clause to be any value not greater than delta. (If the compiler cannot conform to this small value, it has to reject the declaration.)
For Decimal Fixed Point types, the small is defined to be the delta, which in turn must be an integer power of ten. (Thus you cannot specify the small by an attribute clause.)
For example, if you define a decimal fixed point type with a delta of 0.1, you will be able to accurately store the values 0.1, 1.0, 2.2, 5.7, etc. You will not be able to accurately store the value 0.01. Instead, the value will be rounded down to 0.0.
If the compiler accepts your fixed point type definition, it guarantees that values represented by that type will have at least the degree of accuracy specified (or better). If the compiler cannot support the type definition (e.g. due to limited hardware) then a compile-time error will result.
Ordinary Fixed Point
For an ordinary fixed point, you just define the delta and a range:
The delta can be any real value — for example you may define a circle with one arcsecond resolution with:
[There is one rather strange rule about fixed point types: Because of the way they are internally represented, the range might only go up to
'Last - Delta. This is a bit like a circle — the 0° and 360° mark is also the same.]
It should be noted that in the example above the smallest possible value used is not . The compiler will choose a smaller value which, by default, is an integer power of 2 not greater than the delta. In our example this could be . In most cases this should render better performance but sacrifices precision for it.
If this is not what you wish and precision is indeed more important, you can choose your own small value via the attribute clause 'Small.
As internal representation, you will get a 32 bit signed integer type.
Decimal Fixed Point
You define a decimal fixed point by defining the delta and the number of digits needed:
Delta must be a positive or negative integer power of 10 — otherwise the declaration is illegal.
If you like, you can also define the range needed:
Differences between Ordinary and Decimal Fixed Point Types
There is an alternative way of declaring a "decimal" fixed point: You declare an ordinary fixed point and use an integer power of 10 as 'Small. The following two declarations are equivalent with respect to the internal representation:
-- ordinary fixed point type Duration is delta 10.0**(-9) range -1.0 .. 1.0; for Duration'Small use 10.0**(-9);
You might wonder what the difference then is between these two declarations. The answer is:
None with respect to precision, addition, subtraction, multiplication with integer values.
The following is an incomplete list of differences between ordinary and decimal fixed point types.
- Decimal fixed point types are intended to reflect typical COBOL declarations with a given number of digits.
- Truncation is required for decimal, not for ordinary, fixed point in multiplication and division (RM 4.5.5: (21) (Annotated)) and type conversions. Operations on decimal fixed point are fully specified, which is not true for ordinary fixed point.
- The following attributes are only defined for decimal fixed point: T'Digits (RM 3.5.10: (10) (Annotated)) corresponds to the number of decimal digits that are representable; T'Scale (RM 3.5.10: (11) (Annotated), taken from COBOL) indicates the position of the point relative to the rightmost significant digits; T'Round (RM 3.5.10: (12) (Annotated)) can be used to specify rounding on conversion.
- Package Decimal (RM F.2 (Annotated)), which of course applies only to decimal fixed point, defines the decimal Divide generic procedure. If annex F is supported (GNAT does), at least 18 digits must be supported (there is no such rule for fixed point).
- Decimal_IO (RM A.10.1: (73) (Annotated)) has semantics different from Fixed_IO (RM A.10.1: (68) (Annotated)).
- Static expressions must be a multiple of the Small for decimal fixed point.
Conclusion: For normal numeric use, an ordinary fixed point (probably with 'Small defined) should be defined. Only if you are interested in COBOL like use, i.e. well defined deterministic decimal semantics (especially for financial computations, but that might apply to cases other than money) should you take decimal fixed point.
- Ada Programming
- Ada Programming/Types
- Ada Programming/Types/range
- Ada Programming/Types/digits
- Ada Programming/Types/mod
- Ada Programming/Keywords/delta
- Ada Programming/Attributes/'Small