Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在多个维度中循环_Algorithm_Loops_Delphi_Iteration - Fatal编程技术网

Algorithm 在多个维度中循环

Algorithm 在多个维度中循环,algorithm,loops,delphi,iteration,Algorithm,Loops,Delphi,Iteration,我有一个由多个变量组成的函数f(例如3个变量f(x,y,z))。我想计算每个变量范围的函数结果,并将它们存储在列表中。对于3个变量,可以如下所示: procedure LoopOver3Dimensions; type TListItem=record x, y, z: Real; CalculationResult: Real; end; var List: TList<TListItem>; NewListItem: TListItem; i,

我有一个由多个变量组成的函数
f
(例如3个变量
f(x,y,z)
)。我想计算每个变量范围的函数结果,并将它们存储在列表中。对于3个变量,可以如下所示:

procedure LoopOver3Dimensions;
type
  TListItem=record
    x, y, z: Real;
    CalculationResult: Real;
  end;
var
  List: TList<TListItem>;
  NewListItem: TListItem;
  i, j, k: Integer;
  x, y, z: Real;
  xStart, yStart, zStart: Real;
  xEnd, yEnd, zEnd: Real;
  NumberOfValuesToCalculateForDimension0: Integer;
  NumberOfValuesToCalculateForDimension1: Integer;
  NumberOfValuesToCalculateForDimension2: Integer;
begin
  //set xStart, xEnd, NumberOfValuesToCalculateForDimension0 etc here

  for i := 0 to NumberOfValuesToCalculateForDimension0 do
  begin
    x:=xStart+i*Abs(xEnd-xStart)/(NumberOfValuesToCalculateForDimension0-1);
    for j := 0 to NumberOfValuesToCalculateForDimension1 do
    begin
      y:=yStart+j*Abs(yEnd-yStart)/(NumberOfValuesToCalculateForDimension1-1);
      for k := 0 to NumberOfValuesToCalculateForDimension2 do
      begin
        z:=zStart+k*Abs(zEnd-zStart)/(NumberOfValuesToCalculateForDimension2-1);
        NewListItem.x:=x;
        NewListItem.y:=y;
        NewListItem.z:=z;
        NewListItem.CalculationResult:=DoCalculation(x, y, z);
        List.Add(NewListItem);
      end;
    end;
  end;
end;
procedure loopover3维;
类型
TListItem=记录
x、 y,z:真实的;
计算结果:真实;
结束;
变量
名单:TList ;;
新列表项:TListItem;
i、 j,k:整数;
x、 y,z:真实的;
xStart、yStart、zStart:Real;
真的;
NumberOfValuesToCalculateForDimension0:整数;
NumberOfValuesToCalculateForDimension1:整数;
NumberOfValuesToCalculateForDimension2:整数;
开始
//在此处设置xStart、xEnd、numberOfValues以计算尺寸0等
对于i:=0到NumberOfValuesToCalculateForDimension0Do
开始
x:=xStart+i*Abs(xEnd xStart)/(用于计算尺寸0-1的数值);
对于j:=0到NumberOfValues以计算尺寸1 do
开始
y:=yStart+j*Abs(是yStart)/(用于计算尺寸1-1的数值);
对于k:=0到NumberOfValuesToCalculateForDimension2 do
开始
z:=zStart+k*Abs(zEnd zStart)/(用于计算尺寸2-1的数值);
NewListItem.x:=x;
NewListItem.y:=y;
NewListItem.z:=z;
NewListItem.CalculationResult:=DoCalculation(x,y,z);
List.Add(NewListItem);
结束;
结束;
结束;
结束;
当然,我可以用同样的方式为3个以上的维度(例如20个维度)编程,但它会变得非常麻烦,因为所有内容都是硬编码的,所以我无法在运行时更改维度的数量


最好的方法是什么?

如评论中所述,为了支持任意数量的参数,最好使用可变长度的数组,而不是参数。这是因为该语言不太支持可变长度参数列表

一旦将所有参数打包为一个数组,就要生成所有可能的组合。这不是一项完全简单的任务。我将向您展示如何在
0
N[I]-1
的范围内,将每个维度设置为整数值,而不是使用实值,其中
I
是维度索引。一旦可以迭代所有这些组合,就可以轻松地扩展到生成真实值

基本概念是维护当前迭代值,该值是递增的。第一个维度是循环的最内层。当它达到最大值时,它将返回到零,并且下一个外部维度将递增。等等下面是一些示例代码:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

procedure IterMultiDim(const N: array of Integer; const Proc: TProc<TArray<Integer>>);
var
  dim: Integer;
  Current: TArray<Integer>;
begin
  SetLength(Current, Length(N));
  while Current[high(N)]<N[high(N)] do begin
    Proc(Current);

    // increment state
    dim := 0;
    while dim<=high(N) do begin
      inc(Current[dim]);
      if Current[dim]=N[dim] then begin
        if dim<high(N) then begin
          Current[dim] := 0;
        end;
      end else begin
        break;
      end;
      inc(dim);
    end;
  end;
end;

procedure WriteIntArray(Arr: TArray<Integer>);
var
  i: Integer;
begin
  for i := 0 to high(Arr) do begin
    Write(Arr[i]);
    if i<high(Arr) then begin
      Write(', ');
    end;
  end;
  Writeln;
end;

procedure Main;
begin
  IterMultiDim([2, 3, 4], WriteIntArray);
end;

begin
  try
    Main;
  except
    on E: Exception do begin
      Writeln(E.ClassName, ': ', E.Message);
    end;
  end;
  Readln;
end.
{$APPTYPE控制台}
使用
System.SysUtils;
过程IterMultiDim(常数N:整数数组;常数Proc:TProc);
变量
dim:整数;
电流:焦油;
开始
设置长度(当前,长度(N));

虽然当前[high(N)]如评论中所述,为了支持任意数量的参数,最好使用可变长度的数组,而不是参数。这是因为该语言不太支持可变长度参数列表

一旦将所有参数打包为一个数组,就要生成所有可能的组合。这不是一项完全简单的任务。我将向您展示如何在
0
N[I]-1
的范围内,将每个维度设置为整数值,而不是使用实值,其中
I
是维度索引。一旦可以迭代所有这些组合,就可以轻松地扩展到生成真实值

基本概念是维护当前迭代值,该值是递增的。第一个维度是循环的最内层。当它达到最大值时,它将返回到零,并且下一个外部维度将递增。等等下面是一些示例代码:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

procedure IterMultiDim(const N: array of Integer; const Proc: TProc<TArray<Integer>>);
var
  dim: Integer;
  Current: TArray<Integer>;
begin
  SetLength(Current, Length(N));
  while Current[high(N)]<N[high(N)] do begin
    Proc(Current);

    // increment state
    dim := 0;
    while dim<=high(N) do begin
      inc(Current[dim]);
      if Current[dim]=N[dim] then begin
        if dim<high(N) then begin
          Current[dim] := 0;
        end;
      end else begin
        break;
      end;
      inc(dim);
    end;
  end;
end;

procedure WriteIntArray(Arr: TArray<Integer>);
var
  i: Integer;
begin
  for i := 0 to high(Arr) do begin
    Write(Arr[i]);
    if i<high(Arr) then begin
      Write(', ');
    end;
  end;
  Writeln;
end;

procedure Main;
begin
  IterMultiDim([2, 3, 4], WriteIntArray);
end;

begin
  try
    Main;
  except
    on E: Exception do begin
      Writeln(E.ClassName, ': ', E.Message);
    end;
  end;
  Readln;
end.
{$APPTYPE控制台}
使用
System.SysUtils;
过程IterMultiDim(常数N:整数数组;常数Proc:TProc);
变量
dim:整数;
电流:焦油;
开始
设置长度(当前,长度(N));

当当前[high(N)]受到David方法的启发时,我想出了另一个解决方案:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

procedure IterMultiDim(const NumberOfCalculationsPerDimension: TArray<Integer>; const Proc: TProc<TArray<Integer>>);

  function ModInc(const MaxNumber: Integer; var AValue: Integer): Boolean;
  begin
    Inc(AValue);
    if AValue>MaxNumber then
    begin
      AValue:=0;
      Result:=true; //carry
    end
    else
    begin
      Result:=false; //no carry
    end;
  end;

var
  NumberOfDimensions: Integer;
  CurrentIndices: TArray<Integer>;
  i, j: Integer;
  TotalNumberOfCalculations: Integer;
  Carry: Boolean;
begin
  NumberOfDimensions:=Length(NumberOfCalculationsPerDimension);
  SetLength(CurrentIndices, NumberOfDimensions);
  TotalNumberOfCalculations:=1;
  for i := 0 to NumberOfDimensions-1 do
  begin
    TotalNumberOfCalculations:=TotalNumberOfCalculations*NumberOfCalculationsPerDimension[i];
  end;

  for i := 0 to TotalNumberOfCalculations-1 do
  begin
    Proc(CurrentIndices);
    Carry:=true;
    for j := 0 to NumberOfDimensions-1 do
    begin
      if Carry then
      begin
        Carry:=ModInc(NumberOfCalculationsPerDimension[j]-1, CurrentIndices[j]);
      end;
    end;
  end;
end;

procedure WriteIntArray(Arr: TArray<Integer>);
var
  i: Integer;
  S: string;
begin
  S:='';
  for i := 0 to High(Arr) do
  begin
    S:=S+Arr[i].ToString+'  ';
  end;
  Writeln(S);
end;

procedure Main;
begin
  IterMultiDim([3, 4, 2], WriteIntArray);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
程序项目1;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils;
程序IterMultiDim(const numberofcalculationperdimension:TArray;const Proc:TProc);
函数ModInc(const MaxNumber:Integer;var AValue:Integer):布尔;
开始
公司(AValue);
如果AValue>MaxNumber,则
开始
AValue:=0;
结果:=真//携带
结束
其他的
开始
结果:=假//禁止携带
结束;
结束;
变量
NumberOfDimensions:整数;
当前指标:焦油;
i、 j:整数;
TotalNumberOfCalculations:整数;
进位:布尔;
开始
NumberOfDimensions:=长度(NumberOfCalculationsPerDimension);
SetLength(当前索引、NumberOfDimensions);
计算总数:=1;
对于i:=0到NumberOfDimensions-1 do
开始
TotalNumberOfCalculations:=TotalNumberOfCalculations*NumberOfCalculations PerDimension[i];
结束;
对于i:=0到TotalNumberOfCalculations-1 do
开始
Proc(当前指数);
进位:=正确;
对于j:=0到NumberOfDimensions-1 do
开始
如果携带的话
开始
进位:=ModInc(每个维度的计算次数[j]-1,当前索引[j]);
结束;
结束;
结束;
结束;
程序写入阵列(Arr:TArray);
变量
i:整数;
S:字符串;
开始
S:='';
对于i:=0至高(Arr)do
开始
S:=S+Arr[i]。ToString+'';
结束;
书面文件(S);;
结束;
主程序;
开始
IterMultiDim([3,4,2],WriteIntArray);
结束;
开始
尝试
主要的;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
Readln;
结束。

受David方法的启发,我想出了另一个解决方案:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

procedure IterMultiDim(const NumberOfCalculationsPerDimension: TArray<Integer>; const Proc: TProc<TArray<Integer>>);

  function ModInc(const MaxNumber: Integer; var AValue: Integer): Boolean;
  begin
    Inc(AValue);
    if AValue>MaxNumber then
    begin
      AValue:=0;
      Result:=true; //carry
    end
    else
    begin
      Result:=false; //no carry
    end;
  end;

var
  NumberOfDimensions: Integer;
  CurrentIndices: TArray<Integer>;
  i, j: Integer;
  TotalNumberOfCalculations: Integer;
  Carry: Boolean;
begin
  NumberOfDimensions:=Length(NumberOfCalculationsPerDimension);
  SetLength(CurrentIndices, NumberOfDimensions);
  TotalNumberOfCalculations:=1;
  for i := 0 to NumberOfDimensions-1 do
  begin
    TotalNumberOfCalculations:=TotalNumberOfCalculations*NumberOfCalculationsPerDimension[i];
  end;

  for i := 0 to TotalNumberOfCalculations-1 do
  begin
    Proc(CurrentIndices);
    Carry:=true;
    for j := 0 to NumberOfDimensions-1 do
    begin
      if Carry then
      begin
        Carry:=ModInc(NumberOfCalculationsPerDimension[j]-1, CurrentIndices[j]);
      end;
    end;
  end;
end;

procedure WriteIntArray(Arr: TArray<Integer>);
var
  i: Integer;
  S: string;
begin
  S:='';
  for i := 0 to High(Arr) do
  begin
    S:=S+Arr[i].ToString+'  ';
  end;
  Writeln(S);
end;

procedure Main;
begin
  IterMultiDim([3, 4, 2], WriteIntArray);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
程序项目1;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils;
过程IterMultiDim(const numberofcalculationperdimension:TArray;const Proc:TProc)