如何在第一个状态下表示具有完整标量范围的数据,然后在使用相同的内存空间时将其表示为下一个状态中的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进行范围检查将涉及额外的代码。
答案 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范围检查的方法。
这使用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;
0.1
11.0
-3.0
Before normalization.
0.100
11.000
-3.000
After normalization.
0.221
1.000
0.000