delphi 无法从函数获取平均值

juud5qan  于 2023-03-08  发布在  其他
关注(0)|答案(2)|浏览(150)

我写了一个函数来尝试确定输入到数组中的所有值的平均值,但是它总是吐出一个大约50的值。有一个简单的方法可以解决这个问题,但是我真的想知道我错在哪里。记住,我还在学习 Delphi ,所以我还有很多东西要学。
我试着写一个函数,它接受一个数组,并通过把数组中的所有值加起来,再除以数组中的值的总数,来确定数组中所有值的平均值。

Function Average(x : array of Integer; var y : Integer): Real;
var
  e : Integer;
  fTotal : Real;
begin

  //Initializing the variable

  fTotal := 0;
  Result := 0;

  //Adding values to fTotal
  
  for e := 1 to y do
  begin
  
    fTotal := fTotal + x[e];
    
  end;

  //Determining Average

  fTotal := fTotal / y;

  //Assigning Average to Result

  Result := fTotal;

  //End of Function
  
end;

x是从中获取值的数组。y是数组中存储的值的数量。
然而,在运行代码时,我发现无论数组中的值是什么,函数的结果似乎总是在50左右。
我试过用这些值。

arrVal : array[1..50] of integer;
var
  iCount : Integer;
  fAverage : Real;
begin
  arrVal[1] := 70;
  arrVal[2] := 80;
  arrVal[3] := 90;

  iCount := 3;  //The amount of values in the array

  fAverage := Average(arrVal, iCount);

我运行代码,函数给我的值是50。我测试了这些值,实际平均值是80。

vsnjm48y

vsnjm48y1#

你已经宣布

function Average(x: array of Integer; var y: Integer): Real;

首先,x在这里是一个开放数组参数,它是一种“神奇的”参数,可以接受静态数组、动态数组或开放数组文本。
在任何情况下,它都包含数组长度的信息,因此根本不需要使用y参数,所以应该将其删除(即使不是这样,也不应该使用var)。
此外,出于性能原因,您需要使用const x: array of Integer--并且不要冒堆栈溢出的风险。
在函数体内部,x的索引范围从Low(x)High(x)x的长度为Length(x)
在这种情况下,当x是一个开放数组参数时,可以保证Low(x) = 0.和High(x) = Length(x) - 1,因此如果x为空,则High(x) = -1生成类似for var i := 0 to High(x) do的循环时不执行迭代。
所以你应该写

function Average(const X: array of Integer): Double;
begin
  if Length(X) = 0 then
    raise Exception.Create('Cannot compute average of empty array.');
  Result := 0;
  for var i := 0 to High(X) do
    Result := Result + X[i];
  Result := Result / Length(X);
end;

执行Length(X) = 0检查纯粹是出于数学原因:一个零的数字列表没有平均值(但是这样一个列表的 sum0product1)。
实际上,您甚至可以使用for in循环:

function Average(const X: array of Integer): Double;
begin
  if Length(X) = 0 then
    raise Exception.Create('Cannot compute average of empty array.');
  Result := 0;
  for var a in X do
    Result := Result + a;
  Result := Result / Length(X);
end;

理论上,Result变量可能在计算过程中溢出。要避免这种情况,您可以改为

function Average(const X: array of Integer): Double;
begin
  if Length(X) = 0 then
    raise Exception.Create('Cannot compute average of empty array.');
  Result := 0;
  const F = 1 / Length(X);
  for var a in X do
    Result := Result + F * a;
end;

在实践中,几乎没有必要重新发明轮子(Math单元):

function Average(const X: array of Integer): Double;
begin
  Result := SumInt(X) / Length(X);
end;
dzhpxtsq

dzhpxtsq2#

我发现了我所犯的错误。
该函数假设数组的第一个元素位于索引1处,这是 Delphi 的情况,但不适用于其他一些编程语言。如果数组的索引为零,则该函数将无法正确处理第一个元素。

for e := 0 to y-1 do
begin
  fTotal := fTotal + x[e];
end;

这就解决了这个问题。看来我忘记了 Delphi 最基本的原则之一。

相关问题