我试图创建它,但实际上并没有用。
这是我希望它如何工作的表。 click to see picture
这是我的数据库图片(在phpmyadmin中)click to see picture
我希望它首先查看百分比,然后找到要使用的百分比。
IE:获得1到50之间的随机数的概率为75%。获得51到200之间的随机数的概率为20%。
这是我的代码:
if ($_GET['method'] == "test") {
$sql = "SELECT 1percentage, 1min, 1max, 2percentage, 2min, 2max, 3percentage, 3min, 3max, 4percentage, 4min, 4max FROM `keys`";
$result = $conn->query($sql);
while($row = $result->fetch_assoc()) {
$total = $row["1percentage"] + $row["2percentage"] + $row["3percentage"] + $row["4percentage"] + 1;
$random = rand(0, $total);
if ($random < $row['1percentage'] || $random == $row['1percentage']) {
$amount = rand($row['1min'], $row['1max']);
} elseif ($random > $row['1percentage'] && $random < $row['2percentage'] || $random == $row['2percentage']) {
$amount = rand($row['2min'], $row['2max']);
} elseif ($random > $row['2percentage'] && $random < $row['3percentage'] || $random == $row['3percentage']) {
$amount = rand($row['3min'], $row['3max']);
} elseif ($random > $row['4percentage'] || $random == $row['4percentage']) {
$amount = rand($row['4min'], $row['4max']);
} else {
exit("0");
}
echo $amount;
}
}
但是它输出的是1到50,或者1001到10000。
那我做错了什么?
答案 0 :(得分:1)
查看您的代码和您提供的数据库记录中的值,您当前的设置将无效。
首先,应按以下方式清理if
语句:
if ($_GET['method'] == "test") {
$sql = "SELECT 1percentage, 1min, 1max, 2percentage, 2min, 2max, 3percentage, 3min, 3max, 4percentage, 4min, 4max FROM `keys`";
$result = $conn->query($sql);
while($row = $result->fetch_assoc()) {
$total = $row['1percentage'] + $row['2percentage'] + $row['3percentage'] + $row['4percentage'] + 1;
$random = rand(0, $total);
if ($random <= $row['1percentage']) {
$amount = rand($row['1min'], $row['1max']);
} elseif ($random > $row['1percentage'] && $random <= $row['2percentage']) {
$amount = rand($row['2min'], $row['2max']);
} elseif ($random > $row['2percentage'] && $random <= $row['3percentage']) {
$amount = rand($row['3min'], $row['3max']);
} elseif ($random >= $row['4percentage']) {
$amount = rand($row['4min'], $row['4max']);
} else {
exit("0");
}
echo $amount;
}
}
这不仅使脚本更有效,而且使代码更易于理解,并且希望更容易调试。
第二,要使其正常工作,您需要从1%的最小百分比开始,然后从1%开始增加,因为您的条件在这些值之间使用大于/小于-范围。例如,看第二种情况:
if ($random > $row['1percentage'] && $random <= $row['2percentage'])
在您发布的屏幕截图中,我们看到1%(75)大于2%(20)。由于任何数字都不能大于75,也不能小于或等于20,因此永远不会满足此条件。条件3和4相似。因此,唯一可能满足的两个条件是第一个条件和最后一个条件。通过当前设置,任何大于或等于1%(在这种情况下为75)的数字都将满足第一个条件。小于1%且大于等于4%(在这种情况下为1)的任何数字都将满足最后一个条件。
要么以升序重新排列百分比,要么重写条件,并进行一些抽查以确保您得到期望的行为。
另一种可能的方法...
正如@Eugene Anisiutkin所建议的那样,该算法本身需要重新设计。假设他的以下说法是正确的...
“任务是从1到50生成随机数,生成概率为75%,从51到200生成概率为20%,从201到1000生成概率为4%,从1001到10000,发生概率为1%。“
...那么您将需要从1-50生成75个随机数,从51-200生成20个随机数,从201-1000生成4个随机数,并从1001-10000生成1个随机数。将所有随机生成的数字存储在一个数组中之后,您可以生成一个介于0和该数组的最后一个索引(count($randArray)-1
)之间的最终随机数。该随机数将是您要在数组中使用的数字的索引。请记住,“百分比”值只有加起来等于100才是真实百分比。否则,您可以将它们视为“重量”。这种方法不需要“百分比”数字以任何顺序排列。代码看起来像这样:
if ($_GET['method'] == "test") {
$sql = "SELECT 1percentage, 1min, 1max, 2percentage, 2min, 2max, 3percentage, 3min, 3max, 4percentage, 4min, 4max FROM `keys`";
$result = $conn->query($sql);
while($row = $result->fetch_assoc()) {
//store the record values for easy reference
$p1 = $row['1percentage'];
$p1min = $row['1min'];
$p1max = $row['1max'];
$p2 = $row['2percentage'];
$p2min = $row['2min'];
$p2max = $row['2max'];
$p3 = $row['3percentage'];
$p3min = $row['3min'];
$p3max = $row['3max'];
$p4 = $row['4percentage'];
$p4min = $row['4min'];
$p4max = $row['4max'];
$randomArray = array();
for($i = 0; $i < $p1; $i++){
$newRandom = rand($p1min, $p1max); //generate appropriate random number
array_push($randomArray, $newRandom); //add the random number to the array
}
for($i = 0; $i < $p2; $i++){
$newRandom = rand($p2min, $p2max); //generate appropriate random number
array_push($randomArray, $newRandom); //add the random number to the array
}
for($i = 0; $ i < $p3; $i++){
$newRandom = rand($p3min, $p3max); //generate appropriate random number
array_push($randomArray, $newRandom); //add the random number to the array
}
for($i=0;$i<$p4;$i++){
$newRandom = rand($p4min, $p4max); //generate appropriate random number
array_push($randomArray, $newRandom); //add the random number to the array
}
//get last index of array
$uBound = count($randomArray)-1;
//get a random index
$randomIndex = rand(0, $uBound);
$amount = $randomArray[$randomIndex];
echo $amount;
}
}
答案 1 :(得分:1)
这是一个有趣的问题,我认为以前已经解决过。
Python的random.choices
函数解决了与此类似的问题。
这是尝试将其转换为适合当前用例的PHP。
# https://github.com/python/cpython/blob/master/Lib/bisect.py#L22
function bisect(array $a, float $x, int $lo, int $hi): int {
$mid = $lo + $hi;
while ($lo < $hi) {
$mid = ($lo + $hi) / 2;
if ($x < $a[$mid]) {
$hi = $mid;
} else {
$lo = $mid + 1;
}
}
return $lo;
}
/*
* Generate a random number
* from 1 to 50, with the generation probability 75%,
* from 51 to 200 with the generation probability 20%,
* from 201 to 1000 with the generation probability 4% and
* from 1001 to 10000 with the generation probability 1%.
*/
function randomChoice(array $population, array $weights): int
{
$cummWeights = array_reduce($weights, function ($acc, $curr) {
$lastSlice = array_slice($acc, -1);
$acc[] = $lastSlice[0] + $curr;
return $acc;
}, [0]);
# remove 0 starting value
array_shift($cummWeights);
$lastWeightSlice = array_slice($cummWeights, -1);
$total = $lastWeightSlice[0];
$probability = ((float)rand() / (float)getrandmax());
$needle = $probability * $total;
# look for $needle in $cummWeights, then use that to select which population distribution to generate a random number from.
# https://github.com/python/cpython/blob/master/Lib/random.py#L387
$index = bisect($cummWeights, $needle, 0, count($population));
$distribution = $population[$index];
return rand($distribution[0], $distribution[1]);
}
echo randomChoice(
[
[51, 200],
[1, 50],
[201, 1000],
[1001, 10000]
],
[20, 75, 4, 1]
);
答案 2 :(得分:0)
花了一些时间解决这个问题后,我想出了一个略有不同的解决方案。在示例中,概率的实现很糟糕,但是它确实显示了对于几乎任何数量的生成数据都达到所需概率的基本示例。如果您将$how_much_numbers_to_generate
变量设置为至少小于50,则下面的代码将无法正常工作,但这就是概率的方法。数据集必须相当大才能获得一定的准确概率。同样,为了使示例正常工作,您必须将$mysqli = new mysqli("localhost", "my_name", "my_pass", "my_database");
中的用户名,密码和数据库替换为所使用的用户名,密码和数据库。完整代码如下
<?php
$mysqli = new mysqli("localhost", "my_username", "my_password", "my_database");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$how_much_numbers_to_generate = 1000;
$result = $mysqli->query("SELECT 1percentage, 1min, 1max, 2percentage, 2min, 2max, 3percentage, 3min, 3max, 4percentage, 4min, 4max FROM percentages");
while($row = $result->fetch_assoc())
{
$first_percentage = $row['1percentage'];
$first_min = $row['1min'];
$first_max = $row['1max'];
$second_percentage = $row['2percentage'];
$second_min = $row['2min'];
$second_max = $row['2max'];
$third_percentage = $row['3percentage'];
$third_min = $row['3min'];
$third_max = $row['3max'];
$fourth_percentage = $row['4percentage'];
$fourth_min = $row['4min'];
$fourth_max = $row['4max'];
$first_numbers_generated=0;
$second_numbers_generated=0;
$third_numbers_generated=0;
$fourth_numbers_generated=0;
$random_array = array();
for($numbers_generated=0; $numbers_generated < $how_much_numbers_to_generate; $numbers_generated++)
{
if( $first_numbers_generated==0 || $first_numbers_generated/$numbers_generated * 100.0 <= $first_percentage)
{
$random_value = rand($first_min, $first_max);
$first_numbers_generated++;
}
else if( $second_numbers_generated==0 || $second_numbers_generated/$numbers_generated * 100.0 <= $second_percentage)
{
$random_value = rand($second_min, $second_max);
$second_numbers_generated++;
}
else if( $third_numbers_generated==0 || $third_numbers_generated/$numbers_generated * 100.0 <= $third_percentage)
{
$random_value = rand($third_min, $third_max);
$third_numbers_generated++;
}
else if( $fourth_numbers_generated==0 || $fourth_numbers_generated/$numbers_generated * 100.0 <= $fourth_percentage)
{
$random_value = rand($fourth_min, $fourth_max);
$fourth_numbers_generated++;
}
else
{
$random_value = rand($first_min, $fourth_max);
if ($random_value <= $first_max)
{
$first_numbers_generated++;
}
else if ($random_value <= $second_max)
{
$second_numbers_generated++;
}
else if ($random_value <= $third_max)
{
$third_numbers_generated++;
}
else
{
$fourth_numbers_generated++;
}
}
array_push($random_array, $random_value);
}
echo "First numbers generated: " . $first_numbers_generated . "<br/>";
echo "Second numbers generated: " . $second_numbers_generated . "<br/>";
echo "Third numbers generated: " . $third_numbers_generated . "<br/>";
echo "Fourth numbers generated: " . $fourth_numbers_generated . "<br/>";
echo "First probability: " . ($first_numbers_generated/$numbers_generated * 100.0) . "<br/>";
echo "Second probability: " . ($second_numbers_generated/$numbers_generated * 100.0) . "<br/>";
echo "Third probability: " . ($third_numbers_generated/$numbers_generated * 100.0) . "<br/>";
echo "Fourth probability: " . ($fourth_numbers_generated/$numbers_generated * 100.0) . "<br/>";
}