我正在寻找一种将 0 到 1(含)之间的浮点值转换为数组索引的方法。
这个想法是根据浮点概率值随机选择一个数组元素。我想出了下面的代码,它尝试执行此操作 1000 次。然后跟踪 $counts 数组中每个值被选择的频率。
get_rand_index_1() 函数使用 round(),其中 $count - 1。这里的问题是第一个和最后一个索引(在本例中为 0/Apples 和 5/Pineapples)被选择的频率只有一半。导致 $counts 类似于:
Array
(
[Apples] => 142
[Oranges] => 236
[Bananas] => 269
[Pineapples] => 104
[Pears] => 249
)
我还写了get_rand_index_2()。这里使用floor()代替round(),使用$count代替($count - 1)。我认为这可以完成工作,但如果浮点数为 1,则会出现问题。在这种情况下,索引将无效。当然,这是极不可能的,但理论上仍然是可能的。如果一次生成数百万个随机值,可能会出现问题。
所以我减去了 1 / mt_getrandmax()。然后,在极少数情况下,数字变为负值,我使用了 max(0, ...)。
我认为这个 get_rand_index_2() 有效,生成的 $counts 数组似乎具有均匀分布的值。但这似乎有点老套。我也不确定这是否是最有效的方法。
是否有更优雅或更高效的方式来完成我想要的事情?
这是我正在测试的代码。
<?php
$array = ["Apples", "Bananas", "Oranges", "Pears", "Pineapples"];
$count = count($array);
$counts = [];
for ($i = 0; $i < 1000; $i++) {
//$index = get_rand_index_1($count);
$index = get_rand_index_2($count);
$value = $array[$index];
if (!isset($counts[$value])) $counts[$value] = 1;
else $counts[$value]++;
}
print_r($counts);
function get_rand_index_1(int $count)
{
$float_rand = mt_rand() / mt_getrandmax();
$index = round($float_rand * ($count - 1));
return $index;
}
function get_rand_index_2(int $count)
{
$float_rand = max(0, mt_rand() / mt_getrandmax() - 1 / mt_getrandmax());
$index = floor($float_rand * $count);
return $index;
}
尝试下面的函数,通过将随机
float
缩放到数组长度,使用下限进行舍入,并确保索引保持在范围内,来均匀分布随机索引选择。
function get_rand_index(int $count) {
$float_rand = mt_rand() / mt_getrandmax();
$index = floor($float_rand * $count);
$index = min($index, $count - 1);
return $index;
}