Algorithm 将一个数拆分为随机的非零数
我有几对数字,比如说Algorithm 将一个数拆分为随机的非零数,algorithm,math,Algorithm,Math,我有几对数字,比如说 [X1,Y1], [X2,Y2] ..... [Xn,Yn] Y > X 我还有一个数字,比如Z。现在我想把Z分成随机值Nm,这样它总是满足以下条件: N1 + N2 + N3 ...... Nn = Z Nm > 0 Nm <= Ym - Xm N1+N2+N3。。。。。。Nn=Z 纳米>0 Nm如果序列y_1-x_1+…+y_m-x_my_m-x_m 前NNI的每个Ni i总计达上界,因为它是一个随机数在0和1之间的上界,最后一个值落在范
[X1,Y1], [X2,Y2] ..... [Xn,Yn] Y > X
我还有一个数字,比如Z。现在我想把Z分成随机值Nm,这样它总是满足以下条件:
N1 + N2 + N3 ...... Nn = Z
Nm > 0
Nm <= Ym - Xm
N1+N2+N3。。。。。。Nn=Z
纳米>0
Nm如果序列y_1-x_1+…+y_m-x_my_m-x_m
前NNI的每个Ni i总计达上界,因为它是一个随机数在0和1之间的上界,最后一个值落在范围内,因为如果没有,我们会循环并再次尝试。数字加起来是Z,因为NYM是Z的差和其余的级数的和。< /P> < P>你有M个区间[席,Yi ]。你需要在每个区间内有一个随机数,这样所有的数之和就是Z
这些数字的总和必须介于和(Xi)和和和(Yi)之间。因此,我们同时计算:
Zmin = 0;
Zmax = 0;
for (i = 0; i < m; i++) {
Zmin += X[i];
Zmax += Y[i];
Z[i] = X[i];
}
这是PHP中的一个快速实现,看起来很有效
<?php
$X = [ 1, 4, 11, 3, 5, 17, 22, 35, 120, 0 ];
$Y = [ 8, 9, 33, 9, 9, 28, 24, 36, 215, 3 ];
$m = count($X);
$ZZ= 0;
// Construct a Z that will work.
for ($i = 0; $i < $m; $i++) {
// $Y[$i] = rand($X[$i], $X[$i] + 20);
$ZZ += rand($X[$i], $Y[$i]);
}
$Zmin = 0;
$Zmax = 0;
for ($i = 0; $i < $m; $i++) {
$Zmin += $X[$i];
$Zmax += $Y[$i];
}
$R = $ZZ - $Zmin;
if (($R < 0) || ($R + $Zmin > $Zmax)) {
die("Can't do.\n");
}
$D = $Zmax - $Zmin;
for ($i = 0; $i < $m; $i++) {
$A = max($R-$D, 0); // Cannot distribute less than this.
$B = min($Y[$i]-$X[$i], $R); // Nor more than this.
$Q = ($B - $A); // This is positive, or we would have failed earlier
assert('$Q > 0');
$Z[$i] = $X[$i] + rand($A, $B); // floor($A + ($B-$A)*rand());
$R -= ($Z[$i] - $X[$i]);
assert('$R >= 0');
assert('$X[$i] <= $Z[$i]');
assert('$Y[$i] >= $Z[$i]');
}
X1
,Y1
等从何而来?您可能想要Xm@MarkDickinson:更正约束如果X1>Z怎么办?可能吗?
remainder = Z - Zmin;
if ((remainder < 0) || (remainder + Zmin > Zmax)) {
// Can't do.
}
// There are several ways of equidistributing the remainder.
// This is not one of them, but it's simple.
// If Z is very near Zmax, performances will suffer.
while (remainder > 0) {
// Choose
i = rand()*m;
// Can we increase Z[i]?
if (Z[i] < Y[i]) {
Z[i]++;
remainder--;
}
}
// DONE!
D = Zmax - Zmin;
for (i = 0; i < m; i++) {
V = MAX(remainder-D, 0);
Q = (Y[i] - X[i]) - V; // This is positive, or we would have failed earlier
Z[i] = Y[i]-X[i]-Q+rand()*(Q*remainder/(D+Q));
remainder -= (Z[i] - X[i]);
}
<?php
$X = [ 1, 4, 11, 3, 5, 17, 22, 35, 120, 0 ];
$Y = [ 8, 9, 33, 9, 9, 28, 24, 36, 215, 3 ];
$m = count($X);
$ZZ= 0;
// Construct a Z that will work.
for ($i = 0; $i < $m; $i++) {
// $Y[$i] = rand($X[$i], $X[$i] + 20);
$ZZ += rand($X[$i], $Y[$i]);
}
$Zmin = 0;
$Zmax = 0;
for ($i = 0; $i < $m; $i++) {
$Zmin += $X[$i];
$Zmax += $Y[$i];
}
$R = $ZZ - $Zmin;
if (($R < 0) || ($R + $Zmin > $Zmax)) {
die("Can't do.\n");
}
$D = $Zmax - $Zmin;
for ($i = 0; $i < $m; $i++) {
$A = max($R-$D, 0); // Cannot distribute less than this.
$B = min($Y[$i]-$X[$i], $R); // Nor more than this.
$Q = ($B - $A); // This is positive, or we would have failed earlier
assert('$Q > 0');
$Z[$i] = $X[$i] + rand($A, $B); // floor($A + ($B-$A)*rand());
$R -= ($Z[$i] - $X[$i]);
assert('$R >= 0');
assert('$X[$i] <= $Z[$i]');
assert('$Y[$i] >= $Z[$i]');
}