不同情况下的标量范围不同

时间:2016-02-29 15:11:31

标签: ada

如何在第一个状态下表示具有完整标量范围的数据,然后在使用相同的内存空间时将其表示为下一个状态中的0到1?

对此问题的任何解决方法都表示赞赏,如果解决方案需要更改,示例过程就不必如此。

实施例

从文件中读取值,然后将其标准化。 Float_Array是原始值,包含直接来自文件的任何范围。 Feature_Array用于标准化值。

type Float_Array is array (Integer range <>) of Float;
type Feature is new Float range 0.0 .. 1.0;
type Feature_Array is array (Integer range <>) of Feature;

第一步是将浮点数读入Float_Array并查找最大值和最小值。

procedure Read (Name : String; Result : out Float_Array; Last : out Integer; Min : out Float; Max : out Float) is
   use Ada.Text_IO;
   use Ada.Float_Text_IO;
   F : File_Type;
begin
   Open (F, In_File, Name);
   for I in Result'Range loop
      exit when End_Of_File (F);
      Get (F, Result (I));
      Min := Float'Min (Min, Result (I));
      Max := Float'Max (Max, Result (I));
      Last := I;
   end loop;
   Close (F);
end;

Float_Array暂时被用于阅读和查找最小值。下一步是规范化所有值。

function Normalize (Value : Float; Min, Max : Float) return Float is
begin
   return (Value - Min) / (Max - Min);
end;

procedure Normalize (Min : Float; Max : Float; Scale : Float; Result : in out Float_Array) is
begin
   for E of Result loop
      E := Normalize (E, Min, Max) * Scale;
   end loop;
end;

规范化后,我希望将值表示为Feature_Array

没有范围检查的错误解决方案。

没有范围检查,因此它不是一个合适的解决方案。将值从1缩放到3不会产生范围检查错误。因此,如果没有范围检查,那么Feature_Array就没有意义了。

   Last : Integer;
   Data : Float_Array (1 .. 100);
   Min : Float := Float'First;
   Max : Float := Float'Last;
begin
   Read ("frequency.lines_of_float", Data, Last, Min, Max);
   Normalize (Min, Max, 1.0, Data);
   -- Normalize (Min, Max, 3.0, Data);
   declare
      The_Features : Feature_Array (Data'Range) with Address => Data'Address;
   begin
      Put (The_Features);
   end;

我在数组上尝试了属性'Valid,即The_Features'Valid,但它仅适用于标量类型。使用'Valid进行范围检查将涉及额外的代码。

2 个答案:

答案 0 :(得分:1)

我认为我终于明白了这里需要什么。您希望具有规范化类型的变量而不是Floats的变量。 (如果是浮点数,则必须经常进行数组叠加,或者有2个变量指向同一地址)。

  Last : Integer;
  The_Features : Feature_Array (1 .. 100);
  Min : Float := Float'First;
  Max : Float := Float'Last;
begin
  declare
    Data : Float_Array (The_Features'Range) with Address => The_Features'Address;
  begin
    Read ("frequency.lines_of_float", Data, Last, Min, Max);
    Normalize (Min, Max, 1.0, Data);
    -- Normalize (Min, Max, 3.0, Data);
  end;
  Put (The_Features);

这应该有效,但请记住,您必须确保Normalize的结果有效。

答案 1 :(得分:0)

似乎手动范围检查是可行的方法。我无法自动找到使用Ada范围检查的方法。

手动检查float数组是否在

范围内

这使用Ada 2012 - conditional expressions。 当变量取决于地址时,有时需要这样做。

A := (for all E of Item (Item'First .. Last) => E'Valid);
Assert (A, "Elements of Item is not within range.");

代码

with Ada.Text_IO;
with Ada.Float_Text_IO;

procedure Main is

   type Float_Array is array (Integer range <>) of Float;
   type Feature is new Float range 0.0 .. 1.0;
   type Feature_Array is array (Integer range <>) of Feature;

   procedure Read (Name : String; Result : out Float_Array; Last : in out Integer; Min : in out Float; Max : in out Float) is
      use Ada.Text_IO;
      use Ada.Float_Text_IO;
      F : File_Type;
   begin
      Open (F, In_File, Name);
      loop
         exit when End_Of_File (F);
         Last := Last + 1;
         Get (F, Result (Last));
         Skip_Line (F);
         Min := Float'Min (Min, Result (Last));
         Max := Float'Max (Max, Result (Last));
         exit when Last = Result'Last;
      end loop;
      Close (F);
   end;

   function Normalize (Value : Float; Min, Max : Float) return Float is ((Value - Min) / (Max - Min));

   procedure Normalize (Min : Float; Max : Float; Scale : Float; Result : in out Float_Array) is
   begin
      for E of Result loop
         E := Normalize (E, Min, Max) * Scale;
      end loop;
   end;

   procedure Put (Item : Feature_Array) is
      use Ada.Float_Text_IO;
      use Ada.Text_IO;
   begin
      for E of Item loop
         Put (Float (E), 3, 3, 0);
         New_Line;
      end loop;
   end;

   procedure Put (Item : Float_Array) is
      use Ada.Float_Text_IO;
      use Ada.Text_IO;
   begin
      for E of Item loop
         Put (E, 3, 3, 0);
         New_Line;
      end loop;
   end;

   procedure Read (Item : out Feature_Array; Last : in out Integer) with
     Pre => Feature_Array'Component_Size = Float_Array'Component_Size,
     Post => (for all E of Item (Item'First .. Last) => E >= 0.0 and E <= 1.0);

   procedure Read (Item : out Feature_Array; Last : in out Integer) is
      Data : Float_Array (Item'Range) with Address => Item'Address;
      Min : Float := Float'Last;
      Max : Float := Float'First;
   begin
      Read ("f.ssv", Data, Last, Min, Max);
      Ada.Text_IO.Put_Line ("Before normalization.");
      Put (Data (Data'First .. Last));
      Normalize (Min, Max, 1.0, Data (Data'First .. Last));
   end;

   F : Feature_Array (-5 .. 10);
   Last : Integer := F'First - 1;

begin

   Read (F, Last);
   Ada.Text_IO.Put_Line ("After normalization.");
   Put (F (F'First .. Last));

end;

f.ssv

0.1
11.0
-3.0

结果

Before normalization.
  0.100
 11.000
 -3.000
After normalization.
  0.221
  1.000
  0.000