あなたは「加重確率分布」のように記述することができるか、技術A」になりたい何discrete distribution「および」Categorical distribution「:
カテゴリ分布が別々に各基本イベントの確率で、K可能基本イベントのいずれかをとることができる確率変数の可能な結果を記述する離散確率分布であります指定された。
- ウィキペディア
、あなたがInverse Methodを使って好きな分布を構築することができますrandom variable with uniform distribution in the range 0 to 1を持って考えます。
まず、配布を正規化します。これは、曲線の下の領域が1に等しいことを確認することを意味します(つまり、体重が100%を超えないようにする)。離散分布の場合、重みの合計が1に等しいことを確認することを意味します。 [ベクトルとして値を取り、同じ方向に単位ベクトルを計算するのと同じです]、各値をとり、値の合計で割ってください。累積分布を取得し、
sum = 3 + 1 + 6 = 10
(normalized)
user 1 = 3/10 = 0.3
user 2 = 1/10 = 0.1
user 3 = 6/10 = 0.6
次へ:これに
(original)
user 1 = 3
user 2 = 1
user 3 = 6
:
はそのため、あなたはここから行きます。つまり、各値に対して、(正規化された)重みは欲しませんが、それの重みと前のすべての値を足したものです。
したがって、あなたは、このために、この
(normalized)
user 1 = 0.3
user 2 = 0.1
user 3 = 0.6
に行く:
$r = (float)rand()/(float)getrandmax();
if ($r <= 0.3) return "user 1"; // user 1 = 0.3
else if ($r <= 0.4) return "user 2"; // user 2 = 0.4
else return "user 3"; // user 3 = 1
注を:
(cumulative)
user 1 = 0.3
user 2 = 0.1 + 0.3 = 0.4
user 3 = 0.6 + 0.3 + 0.1 = 1
最後に、あなたがあなたのrandom variable with uniform distribution in the range 0 to 1を取得し、その下のチェックは、それが落ちる値:範囲はPHP is weirdです。
、[OK]を一度にあるすべて、(醜い)PHPで:
$p = ['user 1' => 3, 'user 2' => 1, 'user 3' => 6];
$s = array_sum($p);
$n = array_map(function($i) use ($p, $s){return $i/$s;},$p);
$a = []; $t = 0;
foreach($n as $k => $i) {$t += $i; $a[$k] = $t;}
$r = (float)rand()/(float)getrandmax();
foreach($a as $k => $i) { if ($r <= $i) return $k; }
Try online。
私たちは理由を理由に再実装しましょう。
まずは、例えば、入力を持つテーブルを必要とする:
SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`
その後、我々は値
SELECT sum(chance) FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input
を合計その後、我々は、我々は
を累計
SELECT id, chance/sum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input CROSS JOIN (SELECT sum(chance) as sum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input) s
を正規化
SELECT id, chance/sum as sum, (@tmp := @tmp + chance/sum) as csum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input CROSS JOIN (SELECT sum(chance) as sum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input) s CROSS JOIN (SELECT @tmp := 0) cheat
その後、我々は
SELECT id from (
SELECT id, chance/sum as sum, (@tmp := @tmp + chance/sum) as csum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input CROSS JOIN (SELECT sum(chance) as sum FROM (SELECT 'user 1' AS `id`, 3 AS `chance`
UNION
SELECT 'user 2' AS `id`, 1 AS `chance`
UNION
SELECT 'user 3' AS `id`, 6 AS `chance`) input) s CROSS JOIN (SELECT @tmp := 0) cheat) a
CROSS JOIN (SELECT RAND() as r) random
WHERE csum > r
LIMIT 1
Try onlineを選びます。
0.01などの問題は何ですか?計算は同じです。 3 /(3 + 1 + 6)= 0,3 => 30%0.03 /(0.03 + 0.01 + 0.06)= 0,3 => 30%これはPHPとは関係なく計算だけです –
@ B001だから、これらの数字は変更することもできます。したがって、ユーザ1 = 1、ユーザ2 = 30、ユーザ3 = 0.01。それでも%を計算して、誰が勝つかを見てください。 –
@LelioFaieta私はtitをmysqlデータベースから100%自動にします。 –