Frage

Declaring ranges in Ada is always done inclusively. If i want a type that has all the integers from 0 to 42 (or as a mathmatical interval: [0, 42]) i declare it as follows:

type zero_to_42 is range 0 .. 42;

If i want to exclude the zero (the range (0, 42]), this is not an issue for discrete types:

type not_zero_to_42 is range (zero_to_42'First + 1) .. zero_to_42'Last;

but i still have to do this manually, there is no zero_to_answer'NextAfterFirst

For floating point types i have no idea how to do this properly. It's simple for excluding the zero, but excluding anything else seems implementation defined to me.

type works is digits 6 range 0.0 .. 42.0
type also_works is new works range (0.0 + works'small) .. 42.0
type broken is new works range 0.0 .. (42.0 - works'small)

since float values near 42.0 have less precision than floating point values near 0.0, 42.0 - works'small is rounded to 42.0 i could of course find a value by hand that works (e.g. 41.9999) but that seems ugly to me and might not work anymore when i change the number of digits that works has.

War es hilfreich?

Lösung 2

The 'Succ and 'Pred attributes can be used on floating-point values to return the next or previous machine numbers. If T is a floating-point type,

T'Succ(X)

is the smallest floating-point "machine number" > X, and

T'Pred(X)

is the largest floating-point machine number < X. Thus:

type Works is digits 6 range 0.0 .. 42.0;
subtype Exclusive is Works range 0.0 .. Works'Pred(42.0);

Or (since the range on the type declaration might not be relevant):

type Digits_6 is digits 6;
subtype Exclusive is Digits_6 range 0.0 .. Digits_6'Pred(42.0);

Or

type Exclusive is digits 6 range 0.0 .. Float'Pred(42.0);

assuming you know Float is a 32-bit IEEE float and Exclusive will also be one.

Andere Tipps

What is can be used here is 'Adjacent(near_value, towards_value)

type works is digits 6 range 0.0 .. 42.0
type also_works is new works range (0.0 + works'small) .. 42.0
type still_works is new works range 0.0 .. works'Adjacent(42.0, 0.0)

this looks for whichever value can be represented by the machine that is closest to near_value in the direction of towards_value

when printing out still_works'last and works'last very likely the result will look/be the same, but comparing the two won't work

declare
  type works is digits 6 range 0.0 .. 42.0
  subtype still_works is works range 0.0 .. works'Adjacent(42.0, 0.0)
begin
  Text_IO.Put_Line(works'Image(works'Last));
  Text_IO.Put_Line(still_works'Image(still_works'Last));
  Text_IO.Put_Line(Boolean'Image(works'Last = still_works'Last));
end;

yields when compiled with gnat:

4.20000E+01
4.20000E+01
FALSE

You might be able to use the Ada 2012 dynamic predicate:

   type Exclusive is new Float range 0.0 .. 42.0
     with Dynamic_Predicate => Exclusive > 0.0 and then Exclusive < 42.0;

but GNAT seems to have troubles with this: GCC 4.8.1 is OK, GNAT GPL 2013 won’t even accept values of 1.0 or 41.0, and GCC 4.9.0-20140119 threw a bug box!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top