在Ada中声明范围总是包含在内。
如果我想要一个包含从0
到42
(或作为数学区间:[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
所拥有的位数时可能不再有用。
答案 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'last
和works'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
也是一个。