我正在创建一个广告系统,可以更频繁地显示出价最高的广告。
这是我正在使用的表结构的一个例子,但是简化了......
+----+----------+------------------------+----------------------+-----+
| id | name | image | destination | bid |
+----+----------+------------------------+----------------------+-----+
| 1 | abc, co | htt.../blah | htt...djkd.com/ | 3 |
+----+----------+------------------------+----------------------+-----+
| 2 | facebook | htt.../blah | htt...djkd.com/ | 200 |
+----+----------+------------------------+----------------------+-----+
| 3 | google | htt.../blah | htt...djkd.com/ | 78 |
+----+----------+------------------------+----------------------+-----+
现在,我现在正在从数据库中选择值,然后将它们插入到数组中并随机选择一个类似于以下内容:
$ads_array = [];
$ads = Ad::where("active", "=", 1)->orderBy("price", "DESC");
if ($ads->count() > 0) {
$current = 0;
foreach ($ads->get() as $ad) {
for ($i = 0; $i <= ($ad->price == 0 ? 1 : $ad->price); $i++) {
$ads_array[$current] = $ad->id;
$current++;
}
}
$random = rand(0,$current-1);
$ad = Ad::where("id", "=", $ads_array[$random])->first();
...
}
因此,基本上它正在做的是,它将广告的ID插入数组1*$bid
次。这是非常低效的,可悲的是(出于显而易见的原因),但这是我想到这样做的最佳方式。
是否有更好的方法从我的数据库中挑选随机广告;虽然仍然给出价较高的投标人更高的展示概率?
答案 0 :(得分:3)
看起来这可能会起作用(但所有功劳都归功于此guy in the comments)
SELECT ads.*
FROM ads
ORDER BY -log(1.0 - rand()) / ads.bid
LIMIT 1
测试此内容的脚本:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;', 'test', 'test');
$times = array();
// repeat a lot to have real values
for ($i = 0; $i < 10000; $i++) {
$stmt = $pdo->query('SELECT ads.* FROM ads ORDER BY -log(1.0 - rand()) / bid LIMIT 1');
$bid = $stmt->fetch()['bid'];
if (isset($times[$bid])) {
$times[$bid] += 1;
} else {
$times[$bid] = 1;
}
}
// echoes the number of times one bid is represented
var_dump($times);
从测试中得出的数字非常好:
// key is the bid, value is the number of times this bid is represented
array (size=3)
200 => int 7106
78 => int 2772
3 => int 122
关于数学解释的进一步参考
可以使用简单的闭合表达式通过反演对许多重要的单变量分布进行采样。这里列出了一些最有用的。
示例4.1(指数分布)。标准指数分布的密度f(x)= e-x,x> 1。 0.如果X有这个分布,那么E(X)= 1,我们写X~Exp(1)。累积分布函数是F(x)= P(X x)= 1-e-x,其中F-1(u)= -log(1-u)。因此,对于U~U(0,1)采用X = - log(1-U),生成标准指数随机变量。互补反演使用X = - log(U)。
速率λ的指数分布> 0(并且平均θ= 1 /λ)对于0 x <0具有PDFλexp(-λx)。 ∞。如果X具有这种分布,那么我们写X~Exp(1)/λ或等效X~θExp(1),这取决于问题是否在速率λ或平均θ方面更自然地表达。我们可以通过取X = - log(1 - U)/λ来生成X.