我有4个号码
a,b,c,d : integers
我需要给每个人分配一个2-7之间的随机数,但是所有四个数字的总数必须是22。
我该怎么做?
发布于 2013-10-19 14:55:49
警告:@DavidHeffernan.已证明此解决方案不统一。
22是一个相当低的数字,因此,以下几点应该工作得相当好:
procedure ShowValues;
const
TOTAL = 22;
VALUE_COUNT = 4;
MIN_VALUE = 2;
MAX_VALUE = 7;
var
Values: array[0..VALUE_COUNT-1] of Integer;
Shortage: Integer;
Candidates: TList<Integer>;
ValueIndex: Integer;
CandidateIndex: Integer;
begin
Assert(VALUE_COUNT * MAX_VALUE >= TOTAL, 'Total can never be reached!');
Assert(VALUE_COUNT * MIN_VALUE <= TOTAL, 'Total is always exceeded!');
Candidates := TList<Integer>.Create;
try
for ValueIndex := 0 to VALUE_COUNT-1 do
begin
Values[ValueIndex] := MIN_VALUE;
Candidates.Add(ValueIndex);
end;
Shortage := TOTAL - VALUE_COUNT * MIN_VALUE;
while Shortage > 0 do
begin
CandidateIndex := Random(Candidates.Count);
ValueIndex := Candidates[CandidateIndex];
inc(Values[ValueIndex]);
if Values[ValueIndex] = MAX_VALUE then
Candidates.Delete(CandidateIndex);
dec(Shortage);
end;
finally
Candidates.Free;
end;
ShowMessage(IntToStr(Values[0]) + ' ' + IntToStr(Values[1]) +
' ' + IntToStr(Values[2]) + ' ' + IntToStr(Values[3]));
end;
所有四个数字都初始化为最小值。然后,虽然我们还没有达到总数,我们随机选择一个数字,仍然可以增加,并增加一个。
发布于 2013-10-20 11:29:52
一种不涉及构建所有可能样本的表格的有效备选方案如下:
编码很简单,并且使用了与我的第一个答案相同的结构:
function GetSample: TValue;
begin
repeat
Result.a := RandomRange(2, 8);
Result.b := RandomRange(2, 8);
Result.c := RandomRange(2, 8);
Result.d := 22 - Result.a - Result.b- Result.c;
until InRange(Result.d, 2, 7);
end;
使用与我的第一个答案相同的测试工具,经验概率质量如下所示:
https://stackoverflow.com/questions/19465347
复制相似问题