Search code examples
delphidelphi-xe6

How to calculate the ranges of Array?


How can I calculate the ranges of an array so I can send it off to multiple threads for processing. This works but only for lower ranges. It doesn't match the high value of array.

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TRange = record
    High: Integer;
    Low: Integer;
  end;
  TRanges = Array of TRange;

procedure Split(const Size: Integer; const Slices: Integer; var Ranges: TRanges);
var
    SliceSize: Integer;
    SliceStart: Integer;
    I: Integer;
begin
    SliceSize := (Size + Slices) div Slices;
    SetLength(Ranges, Slices);
    SliceStart := 0;
    for I := 0 to Slices - 1 do
    begin
        Ranges[I].Low := SliceStart;
        SliceStart := SliceStart + SliceSize;
        if SliceStart > Size then
        SliceStart := Size;
        Ranges[I].High := SliceStart - 1;
    end;
end;

var
  A: TArray<Integer>;
  Ranges: TRanges;
begin
  SetLength(A, 71);
  Split(High(A), 7, Ranges); // split array in to seven ranges
  // 70 is missing from Ranges..
  ReadLn;
end.

Solution

  • You are passing High(A) to the count parameter but you should pass Length(A). High returns the highest index which is one less than the count of elements in a zero based array.

    Also the calculation of SliceSize is wrong. It needs to be like this:

    procedure Split(const Size: Integer; const Slices: Integer;
      var Ranges: TRanges);
    var
      SliceSize: Integer;
      SliceStart: Integer;
      LeftOver: Integer;
      I: Integer;
    begin
      SliceSize := Size div Slices;
      LeftOver := Size mod Slices;
      SetLength(Ranges, Slices);
      SliceStart := 0;
      for I := 0 to Slices - 1 do
      begin
        Ranges[I].Low := SliceStart;
        SliceStart := SliceStart + SliceSize;
        if I < LeftOver then
          Inc(SliceStart);
        Ranges[I].High := SliceStart - 1;
      end;
    end;