如果数组有添加或删除,重新从头开始重新计算平均值可能会相当耗时。
在这种情况下,可能需要计算运行平均值。
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;
我只是看了看柏林的'SumInt',它和你做的基本一样,虽然它跳过了循环(循环展开等)以使事情变得更快一些。它会打开溢出检查,即使它们已关闭(并在之后恢复之前的状态)。所以作者也必须考虑这一点。 FWIW,不是最快的,但是复制并排序数组可能会避免可能发生的溢出。它也可以很早就检测到溢出。毕竟,Mean的结果不会溢出,所以应该可以做到这一点而不会溢出。 –