找到动态数组均值的最简单方法

Easiest way to find the mean of a dynamic array

我创建了一个动态数组,并向它传递了值。是否有查找动态数组均值的快捷方式。

var
  TheMin, TheMax: Integer;  
  x: array of Integer; //Dynamic array declaration
....
TheMin := MinIntValue(x);//I am able to retrieve the minium value of the dynamic array
TheMax := MaxIntValue(x);//I am able to retrieve the maximum value of the dynamic array 

有没有其他方法可以使用 Math 库求平均值。

写这样的函数非常容易

function Mean(const Data: array of Integer): Double; overload;
var
  i: Integer;
begin
  Result := 0.0;
  for i := low(Data) to high(Data) do
    Result := Result + Data[i];
  Result := Result / Length(Data);
end;

我重载了它,以便它可以与 Math 单元中的相同命名函数并排放置。

如果您想使用内置库代码,您可以使用 Math 单元中的 SumInt

TheMean := SumInt(x) / Length(x);

SumInt 使用 Integer 累加器执行求和。这可能比使用浮点累加器的定制函数更快。但是,Integer 累加器可能会溢出,这可能会令人反感。另一方面,Integer 累加器可能比浮点累加器更准确。根据您的使用要求,这些问题可能对您很重要。

在其他情况下,如果输入数组的长度为零,则会引发运行时浮点除以零错误。

如果数组有添加或删除,从头开始重新计算平均值会非常耗时。

在这种情况下,计算 运行 平均值可能是值得的。

function RecalcAverage(OldAverage: double; const OldArray, Additions, Deletions: TIntArray): double; overload;
var
  i: integer;
begin
  i:= Length(OldArray) + Length(Additions) - Length(Deletions);
  WeighingFactor := 1 / i;
  Result:= OldAverage;
  for i:= 0 to Length(Deletions) -1 do begin
    Result:= Result - (Deletions[i] * WeighingFactor);
  end;
  for i:= 0 to Length(Additions) -1 do begin
    Result:= Result + (Additions[i] * WeighingFactor);
  end;
end;

如果手边有 运行 总和,则可以避免舍入误差并计算出精确的平均值。

function RecalcAverage(var RunningTotal: Int64; const OldArray, Additions, Deletions: TIntArray): double; overload;
var
  i: integer;
begin
  for i:= 0 to Length(Deletions) -1 do begin
    RunningTotal:= RunningTotal - Deletions[i];
  end;
  for i:= 0 to Length(Additions) -1 do begin
    RunningTotal:= RunningTotal + Additions[i];
  end;
  Result:= RunningTotal / (Length(OldArray) + Length(Additions) - Length(Deletions));
end;

如果性能是个问题,在一个循环中计算所有需要的值会更有意义。

type
  TStats = record
    MaxVal: integer;
    MinVal: integer;
    Average: double; 
  end;

function CalcStats(const input: TIntArray): TStats;
var
  MinVal, MaxVal: integer;
  Total: Int64;
  i: integer;
begin
  Assert(Length(input) > 0);
  MinVal:= input[0];
  MaxVal:= MinVal;
  Total:= MinVal;
  for i:= 1 to Length(input) -1 do begin
    MinVal:= Min(MinVal, input[i]);
    MaxVal:= Max(MinVal, input[i]);
    Total:= Total + input[i];
  end;
  Result.MinVal:= MinVal;
  Result.MaxVal:= MaxVal;
  Result.Average:= Total / Length(input);
end;