如何在ada中声明非包容性浮点范围?

时间:2014-02-28 14:30:34

标签: range ada

在Ada中声明范围总是包含在内。 如果我想要一个包含从042(或作为数学区间:[0, 42])的所有整数的类型,我将其声明如下:

type zero_to_42 is range 0 .. 42;

如果我想排除零(范围(0, 42]),这不是离散类型的问题:

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

但我仍然必须手动执行此操作,没有zero_to_answer'NextAfterFirst

对于浮点类型,我不知道如何正确地执行此操作。排除零是很简单的,但排除其他任何东西似乎都是我定义的实现。

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)

由于42.0附近的浮点值的精度低于0.0附近的浮点值,因此42.0 - works'small舍入为42.0 我当然可以找到一个有效的值(例如41.9999),但这对我来说似乎很难看,当我改变works所拥有的位数时可能不再有用。

3 个答案:

答案 0 :(得分:2)

这里可以使用的是'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)

这会查找在near_value

方向上距towards_value最近的机器可以表示的任何值

当打印出still_works'lastworks'last时,结果看起来很可能相同,但比较两者是行不通的

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;
使用gnat编译时产生

4.20000E+01
4.20000E+01
FALSE

答案 1 :(得分:1)

您可以使用Ada 2012动态谓词:

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

但GNAT似乎遇到了麻烦:GCC 4.8.1没问题,GNAT GPL 2013甚至不接受1.0或41.0的值,GCC 4.9.0-20140119抛出了一个错误框!

答案 2 :(得分:1)

'Succ'Pred属性可用于浮点值,以返回下一个或上一个机器号。如果T是浮点类型,

T'Succ(X)

是最小的浮点“机器编号”> X

T'Pred(X)

是最大的浮点计算机编号< X。因此:

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

或(因为type声明的范围可能不相关):

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

或者

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

假设您知道Float是32位IEEE浮点数,Exclusive也是一个。