【问题标题】:How do i declare a non inclusive floating point range in ada?如何在 ada 中声明非包含浮点范围?
【发布时间】:2014-03-03 23:44:31
【问题描述】:

在 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 的位数时可能不再有效。

【问题讨论】:

  • 我认为语言没有为浮点类型定义'small;该属性用于定点。实现者可以定义自己的属性,尽管我不确定他们是否可以在语言未定义的地方定义语言定义的属性。在任何情况下,在浮点类型上使用 'small 似乎会给出实现定义的结果并且不可移植。
  • @ajb 正确关于“小但有浮点类型的分数属性”。还允许实现添加新的(非标准)属性,但它们必须记录在用户指南中。可以使用 pragma(不记得是哪一个)来禁止实现定义的属性。
  • @darkestkhan (1) 'Fraction 在正数上总是返回 0.5 和 1 之间的结果,所以这里不适合。 (2) RM 4.1.4(12) 说新属性通常不能与语言定义的属性具有相同的标识符,因此除非在 Ada 83 中定义,否则实现不应定义自己的'small。 (3 ) pragma Restrictions(No_Implementation_Attributes) 就是你要找的东西。

标签: range ada


【解决方案1】:

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

这会查找在towards_value方向上最接近near_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

【讨论】:

  • 我认为works'Pred(42.0) 应该是等价的,尽管'Adjacent 可能会使意图更清晰。
  • 'Pred'Succ 是我想要的!谢谢!如果您添加答案,我将选择它作为正确答案。
【解决方案2】:

'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 也是一个。

【讨论】:

    【解决方案3】:

    您也许可以使用 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 抛出了一个错误框!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      相关资源
      最近更新 更多