Ada通用平均函数

Ada通用平均函数,ada,Ada,我有一个函数,它从一组记录中取某个数值的平均值。此值是自然类型增量或枚举类型增量。我可以正确地求和值,但我的问题是:如何将数组的长度转换为泛型类型,以便它可以拆分整数和增量类型的数字?在记录数组中使用“长度”属性;这样做的好处是,即使您的边界有点奇怪,比如-18..3,或者枚举,比如奶酪..水果,也可以一直工作 比如: Function Average( Input : In Array_of_Records ) Return float is -- You say you already

我有一个函数,它从一组记录中取某个数值的平均值。此值是自然类型增量或枚举类型增量。我可以正确地求和值,但我的问题是:如何将数组的长度转换为泛型类型,以便它可以拆分整数和增量类型的数字?

在记录数组中使用“长度”属性;这样做的好处是,即使您的边界有点奇怪,比如-18..3,或者枚举,比如奶酪..水果,也可以一直工作

比如:

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;