我有一个类似这样的表格:
ID chance
1 1
2 2
3 4
4 1
现在我需要从这个表中选择一个 rand()。
SELECT * FROM table
ORDER BY RAND()
LIMIT 1
但是,与ID #1和4相比,ID #2被选中的机会增加了一倍。同样地,与ID #1和4相比,ID #3被选中的机会增加了四倍。
有点类似于基于概率的彩票。
我有一个类似这样的表格:
ID chance
1 1
2 2
3 4
4 1
SELECT * FROM table
ORDER BY RAND()
LIMIT 1
1 + 2 + 4 + 1 = 8
)。1..max
(当前示例中的max
为8
)之间的值,包括max
。5
。我们的比较步骤如下:
0 < 5 <= (0) + 1
为false,因此我们没有得到ID1。左侧为0,因为我们从0开始计算。1 < 5 <= (1) + 2
为false,因此我们没有得到ID2。1 + 2 < 5 <= (1 + 2) + 4
为true,因此我们得到ID3。var rewards = [
{ id: 1, chance: 1 },
{ id: 2, chance: 2 },
{ id: 3, chance: 4 },
{ id: 4, chance: 1 }
];
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generate() {
var sum = 0;
var next_sum = 0;
var random = getRandomInt(1, rewards.reduce(function(pv, cv) {
return pv + cv.chance;
}, 0));
for (var i = 0; i < rewards.length; i++) {
next_sum = sum + rewards[i].chance;
if ((random > sum) && (random <= next_sum)) {
return rewards[i].id;
}
sum += rewards[i].chance;
}
}
var winnerCounts = {}, i, winner;
for (i = 0; i < 8000; i++) {
winner = generate();
winnerCounts[winner] = (winnerCounts[winner] || 0) + 1;
}
console.log("Number of times each id was selected after %d itrations", i);
console.log(winnerCounts);
这里有一个仅使用MySQL的解决方案,可以访问SQL Fiddle
select * from (
select id, @running_total as previous_total, @running_total := @running_total + chance AS running_total, until.rand
from (
select round(rand() * init.max) as rand from (
select sum(chance) - 1 as max from demo
) as init
) as until,
demo,
( select @running_total := 0.00 ) as vars
) as results
where results.rand >= results.previous_total and results.rand < results.running_total
max
中[0,max)
内生成一个随机数previous_total(初始值为0)
和current_total
[previous_total,current_total)
的行[0,sum_of_all_chances)
中选择每个数字,所以我们可以将每个条目分配为该条目被选中的机会数量的数字,在这个区间中确保均匀分布。
@running_total
只是一个MySQL变量,我使用(select @running_total := 0.00) as vars
只是为了给它一个初始值。此外,我使用(
select round(rand() * init.max) as rand from (
select sum(chance) - 1 as max from demo
) as init
) as until
只是为了总结机会并存储由MySQL的rand
函数生成的随机数字。希望这样能使代码易于理解。这里是关于从指数分布中选择随机数的内容 http://www.tushar-mehta.com/publish_train/xl_vba_cases/0806%20generate%20random%20numbers.shtml 这是一个简单的代码,"仅供测试"。SELECT id FROM `table` ORDER BY -LOG(1-RAND())/chance LIMIT 1
$sql = "SELECT id FROM `table` ORDER BY -LOG(1-RAND())/chance LIMIT 1";
$Res=array();
for ($i=0;$i<10000;$i++) {
$result = mysqli_query($db,$sql);
$row=mysqli_fetch_array($result, MYSQLI_ASSOC);
if (isset($row['id'])) {
echo "$i. => ".($row['id'])."\n";
if (!isset($Res[$row['id']])) $Res[$row['id']]=0;
$Res[$row['id']]++;
} else {
echo ' error.432 ';exit;
}
}
print_r($Res);