user3841593
user3841593

Reputation: 45

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.

Upvotes: 0

Views: 311

Answers (1)

Stefan Glienke
Stefan Glienke

Reputation: 21748

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;

Upvotes: 5

Related Questions