Delphi 等分其余部分 (MOD)
Delphi Division with equal splitting of the rest (MOD)
我有一个数学问题,我试图用 Delphi 函数来解决。我试图将一个整数分成(几乎)相等的部分。示例:
你有 10 个测试用例,你想分 3 个部分执行它们。因此,平衡工作负载的最佳方法是执行 3、3 和 4 而不是 1、1 和 8。
procedure calc_stream_numbers;
var div_res,rest:double;
total,streams:integer;
begin
total := 10;
streams := 3;
div_res := total DIV streams;
rest := total MOD streams;
showmessage('Items: ' +IntToStr(total)+#13#10+
'Streams: '+IntToStr(streams)+#13#10+
'Result: '+FloatToStr(div_res)+
'Rest: '+FloatToStr(rest));
end;
这给了我 10 / 3 = 3 (Rest 1) 的除法结果,所以我可以执行 3 x 3 个测试用例,总共有 9 个。要执行全部 10 个,我必须将剩余的一个添加到 3 个流中的任何一个。但是如果你有一个更复杂的例子..
我确定有一个数学表达式可以解决这个问题,但我必须承认,我没有任何线索。也许你能告诉我这样的划分是如何调用的,是否有任何内置的delphi函数。
此函数将计算一个整数数组,其中包含每个测试用例的平衡工作负载。
function SplitInteger(Value: Integer; divisor: Integer): TArray<Integer>;
var
d,i : Integer;
begin
SetLength(Result,divisor);
if (divisor = 0) then
Exit;
d := Value div divisor;
for i := 0 to divisor - 1 do
Result[i] := d;
// Fill up with the remains
for i := 0 to (value mod divisor) - 1 do
Inc(Result[i]);
end;
你可以这样编码:
function BalancedWorkload(Total, Count: Integer): TArray<Integer>;
var
i: Integer;
begin
SetLength(Result, Count);
for i := 0 to Count-1 do
begin
Result[i] := Total div Count;
dec(Total, Result[i]);
dec(Count);
end;
end;
您有 Total
个单元可以分成 Count
个部分。我们从第一项 Total div Count
开始。然后我们还剩下 Total - (Total div Count)
个单元,需要拆分成 Count - 1
个部分。以此类推,直到无事可做为止。
这个算法可以很容易地写成递归的方式,但上面的迭代方法对我来说似乎更简单。
您的整个方法假设您可以提前预测每项任务需要多长时间。但是,如果出于某种原因,某些任务比其他任务花费的时间更长怎么办?那么你的方法将不会有效。更好的方法是拥有一个线程安全的任务队列。让每个消费者从队列中拉取任务并处理它们,直到没有任务剩余。
这里是:http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
一个维度是工作量,另一个维度是工人数量
好吧,2D 图形的目标是吸引眼球,因此要在 "short" 个部分中公平地分配 "long" 个部分。
在您的情况下,我们可以将所有 "long" 个偏向一端。
function SplitIntoEqualParts(Total, Count: Integer): TArray<Integer>;
var
i: Integer;
delta, delta1, extra: Word;
begin
Assert( Count < High(Word) ); // RTL DivMod limitation
SetLength(Result, Count);
DivMod(Total, Count, delta, extra);
// one division operation is 2 times faster than two separate operations :-D
delta1 := Succ(delta);
for i := 0 to extra-1 do
Result[i] := delta1;
for i := extra to Count-1 do
Result[i] := delta;
end;
- http://delphi.about.com/library/rtl/blrtlDivMod.htm
- Is there a DivMod that is *not* Limited to Words (<=65535)?
- How do I implement an efficient 32 bit DivMod in 64 bit code
我有一个数学问题,我试图用 Delphi 函数来解决。我试图将一个整数分成(几乎)相等的部分。示例:
你有 10 个测试用例,你想分 3 个部分执行它们。因此,平衡工作负载的最佳方法是执行 3、3 和 4 而不是 1、1 和 8。
procedure calc_stream_numbers;
var div_res,rest:double;
total,streams:integer;
begin
total := 10;
streams := 3;
div_res := total DIV streams;
rest := total MOD streams;
showmessage('Items: ' +IntToStr(total)+#13#10+
'Streams: '+IntToStr(streams)+#13#10+
'Result: '+FloatToStr(div_res)+
'Rest: '+FloatToStr(rest));
end;
这给了我 10 / 3 = 3 (Rest 1) 的除法结果,所以我可以执行 3 x 3 个测试用例,总共有 9 个。要执行全部 10 个,我必须将剩余的一个添加到 3 个流中的任何一个。但是如果你有一个更复杂的例子..
我确定有一个数学表达式可以解决这个问题,但我必须承认,我没有任何线索。也许你能告诉我这样的划分是如何调用的,是否有任何内置的delphi函数。
此函数将计算一个整数数组,其中包含每个测试用例的平衡工作负载。
function SplitInteger(Value: Integer; divisor: Integer): TArray<Integer>;
var
d,i : Integer;
begin
SetLength(Result,divisor);
if (divisor = 0) then
Exit;
d := Value div divisor;
for i := 0 to divisor - 1 do
Result[i] := d;
// Fill up with the remains
for i := 0 to (value mod divisor) - 1 do
Inc(Result[i]);
end;
你可以这样编码:
function BalancedWorkload(Total, Count: Integer): TArray<Integer>;
var
i: Integer;
begin
SetLength(Result, Count);
for i := 0 to Count-1 do
begin
Result[i] := Total div Count;
dec(Total, Result[i]);
dec(Count);
end;
end;
您有 Total
个单元可以分成 Count
个部分。我们从第一项 Total div Count
开始。然后我们还剩下 Total - (Total div Count)
个单元,需要拆分成 Count - 1
个部分。以此类推,直到无事可做为止。
这个算法可以很容易地写成递归的方式,但上面的迭代方法对我来说似乎更简单。
您的整个方法假设您可以提前预测每项任务需要多长时间。但是,如果出于某种原因,某些任务比其他任务花费的时间更长怎么办?那么你的方法将不会有效。更好的方法是拥有一个线程安全的任务队列。让每个消费者从队列中拉取任务并处理它们,直到没有任务剩余。
这里是:http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
一个维度是工作量,另一个维度是工人数量
好吧,2D 图形的目标是吸引眼球,因此要在 "short" 个部分中公平地分配 "long" 个部分。 在您的情况下,我们可以将所有 "long" 个偏向一端。
function SplitIntoEqualParts(Total, Count: Integer): TArray<Integer>;
var
i: Integer;
delta, delta1, extra: Word;
begin
Assert( Count < High(Word) ); // RTL DivMod limitation
SetLength(Result, Count);
DivMod(Total, Count, delta, extra);
// one division operation is 2 times faster than two separate operations :-D
delta1 := Succ(delta);
for i := 0 to extra-1 do
Result[i] := delta1;
for i := extra to Count-1 do
Result[i] := delta;
end;
- http://delphi.about.com/library/rtl/blrtlDivMod.htm
- Is there a DivMod that is *not* Limited to Words (<=65535)?
- How do I implement an efficient 32 bit DivMod in 64 bit code