Ada通用平均函数
我有一个函数,它从一组记录中取某个数值的平均值。此值是自然类型增量或枚举类型增量。我可以正确地求和值,但我的问题是:如何将数组的长度转换为泛型类型,以便它可以拆分整数和增量类型的数字?在记录数组中使用“长度”属性;这样做的好处是,即使您的边界有点奇怪,比如-18..3,或者枚举,比如奶酪..水果,也可以一直工作 比如:Ada通用平均函数,ada,Ada,我有一个函数,它从一组记录中取某个数值的平均值。此值是自然类型增量或枚举类型增量。我可以正确地求和值,但我的问题是:如何将数组的长度转换为泛型类型,以便它可以拆分整数和增量类型的数字?在记录数组中使用“长度”属性;这样做的好处是,即使您的边界有点奇怪,比如-18..3,或者枚举,比如奶酪..水果,也可以一直工作 比如: Function Average( Input : In Array_of_Records ) Return float is -- You say you already
Function Average( Input : In Array_of_Records ) Return float is
-- You say you already have a summation function, so...
Sum : Natural:= Summation( Input );
Begin
Return Sum / Input'Length;
End Average;
您可能需要转换数字类型,比如说Float(Sum)之类,因为Ada没有自动键入“promotions”。在Shark8上稍微扩展一下 Ada允许您将数组类型声明为无约束。差不多
type Array_of_Records is array (Natural range <>) of My_Record;
在这个例程中,我如何知道数组边界在哪里?通过使用属性,如下所示:
function Sum (Vector : in Array_of_Records) return Natural;
for index in Vector'first..Vector'last loop
或
当然,要使它起作用,您必须将一个完美大小的数组传递给求和例程。补充说那不是你所拥有的。假设您有一个巨大的数组(类似于缓冲区),并且不是所有的值都是有效的?那么,您可以跟踪哪些是有效值,并使用切片只传入那些值
(警告-未编译代码)这有一些缺陷,但这是否更接近您想要的 NWS
带有Ada.Text\u Io;
主要程序是
通用的
类型元素是私有的;
零:元素T;
一:元素T ;;
类型Vec_T是元素的数组(整数范围);
使用函数“+”(左、右:在元素中)返回元素;
函数“/”(左、右:元素中)返回元素为;
包装阵列是
函数和(Vec:in-Vec)返回元素;
函数计数(Vec:in-Vec)返回元素;
函数平均值(Vec:in-Vec)返回元素;
末端排列;
包体阵列为
函数和(Vec:in-Vec)返回元素
S:元素_T:=零;
开始
因为我在Vec'First。。最后一个循环
S:=S+Vec(I);
端环;
返回S;
最终金额;
函数计数(Vec:in-Vec)返回元素为
C:元素_T:=零;
开始
因为我在Vec'First。。最后一个循环
C:=C+1;
端环;
返回C;
结束计数;
函数平均值(Vec:in-Vec)返回元素为
S:常数元素_T:=总和(Vec);
Len:常量元素_T:=计数(Vec);
开始
返回S/Len;
最终平均数;
末端排列;
类型Fl_Arr_T是浮点数组(整数范围);
包Fl\u Arr是新的阵列(元素T=>Float,
零=>0.0,
一=>1.0,
Vec\u T=>Fl\u Arr\T);
类型Int\u Arr\T是整数的数组(整数范围);
包Int\u Arr是新的Arrayops(元素T=>Integer,
零=>0,
一=>1,
Vec\u T=>Int\u Arr\T);
我的积分:常数积分(1..5):=(6,7,5,1,2);
My_float:constant flu Arr_T(1..7):=(6.1,7.2,5.3,1.4,2.5,8.7,9.7);
整数和:常量整数:=整数和(我的整数);
整数计数:常量整数:=Int\u Arr.Count(我的整数);
Int_Avg:常量整数:=Int_Arr.Average(My_Ints);
浮动总和:常数浮动:=Fl\U Arr.Sum(我的浮动);
浮动计数:常量浮动:=Fl\U Arr.Count(我的浮动);
浮动平均值:恒定浮动:=浮动平均值(我的浮动);
开始
Ada.Text_Io.Put_Line(“Integers=>Sum:&Integer'Image(Int_Sum)&”,Count:&Integer'Image(Int_Count)&”,Avg:&Integer'Image(Int_Avg));
Ada.Text_Io.Put_Line(“Floats=>Sum:&Float”Image(Float_Sum)和,“Count:&Float”Image(Float_Count)和,“Avg:&Float”Image(Float_Avg));
端干管;
结果:
整数=>总和:21,计数:5,平均值:4
Floats=>Sum:4.09000E+01,Count:7.00000E+00,Avg:5.84286E+00这只返回一个float,我想海报要求的函数将返回一个float或离散类型?真;“or”的“returna float”部分被处理。我将其解释为“它将根据泛型的实例化返回这个或那个”,因为海报要求泛型:)更好的解释;令人遗憾的是,虽然整数和浮点[以及定点]都是“数字”类型,但通用数字类型不可用,而泛型中使用的类型指示符[即“()”或“数字”等]。。。但这可能有很好的原因(编译器的复杂性,人们可能会尝试使用泛型\u number\u 1和泛型\u number\u 2以及试图将两者相加的泛型函数)。如果你看一下实际的类型继承人,那么“实”类型和“整型”类型实际上是两个单独的子树,作为“数值”捆绑在一起。我怀疑这就是泛型不能很好地处理它的原因。看见
for index in Vector'range loop
Rec_Buffer : Array_of_Records (1..10_000);
Last_Valid_Rec : Natural := 0;
....
--// Rec_Buffer gets loaded with 2,128 values or something. We pass it into Sum
--// like so:
Ada.Text_IO ("Sum of vector is " &
natural'image(Sum (Rec_Buffer (1..Last_Valid_Rec));
with Ada.Text_Io;
procedure Main is
generic
type Element_T is private;
Zero : Element_T;
One : Element_T;
type Vec_T is array (Integer range <>) of Element_T;
with function "+"(Left, Right : in Element_T) return Element_T is <>;
with function "/"(Left, Right : in Element_T) return Element_T is <>;
package Arrayops is
function Sum (Vec : in Vec_T) return Element_T;
function Count (Vec : in Vec_T) return Element_T;
function Average (Vec : in Vec_T) return Element_T;
end Arrayops;
package body Arrayops is
function Sum (Vec : in Vec_T) return Element_T is
S : Element_T := Zero;
begin
for I in Vec'First .. Vec'Last loop
S := S + Vec(I);
end loop;
return S;
end Sum;
function Count (Vec : in Vec_T) return Element_T is
C : Element_T := Zero;
begin
for I in Vec'First .. Vec'Last loop
C := C + One;
end loop;
return C;
end Count;
function Average (Vec : in Vec_T) return Element_T is
S : constant Element_T := Sum (Vec);
Len : constant Element_T := Count (Vec);
begin
return S / Len;
end Average;
end Arrayops;
type Fl_Arr_T is array (Integer range <>) of Float;
package Fl_Arr is new Arrayops (Element_T => Float,
Zero => 0.0,
One => 1.0,
Vec_T => Fl_Arr_T);
type Int_Arr_T is array (Integer range <>) of Integer;
package Int_Arr is new Arrayops (Element_T => Integer,
Zero => 0,
One => 1,
Vec_T => Int_Arr_T);
My_Ints : constant Int_Arr_T (1 .. 5) := (6,7,5,1,2);
My_Floats : constant Fl_Arr_T (1 .. 7) := (6.1,7.2,5.3,1.4,2.5,8.7,9.7);
Int_Sum : constant Integer := Int_Arr.Sum (My_Ints);
Int_Count : constant Integer := Int_Arr.Count (My_Ints);
Int_Avg : constant Integer := Int_Arr.Average (My_Ints);
Float_Sum : constant Float := Fl_Arr.Sum (My_Floats);
Float_Count : constant Float := Fl_Arr.Count (My_Floats);
Float_Avg : constant Float := Fl_Arr.Average (My_Floats);
begin
Ada.Text_Io.Put_Line ("Integers => Sum: " & Integer'Image (Int_Sum) & ", Count: " & Integer'Image (Int_Count) & ", Avg: " & Integer'Image (Int_Avg));
Ada.Text_Io.Put_Line ("Floats => Sum: " & Float'Image (Float_Sum) & ", Count: " & Float'Image (Float_Count) & ", Avg: " & Float'Image (Float_Avg));
end Main;