2017-11-23 9 views
0

私は実際にそれを作る方法を知らないところで何かが必要です。ここで%チャンスでランダム化されたPHP

は一例です:私はこれで欲しい

  • ユーザー1 = 3
  • ユーザー2 = 1
  • ユーザー3 = 6

は、そのユーザ1であります30%の確率、2のユーザが10%、および3のユーザが60%である。しかし、これらの数字は、6ではなく0.01にすることもできます。これからは、無作為化されるだけでなく、チャンスもあります。私は本当にそれを説明する方法を知りません。その場合、ユーザー3の確率は60%、ユーザー2の確率は10、ユーザー1の確率は30%です。た​​だし、この最後はできるだけ長くすることができます。これを行う方法?申し訳ありませんが、私は本当に説明が悪いです。

ありがとうございます!

+0

0.01などの問題は何ですか?計算は同じです。 3 /(3 + 1 + 6)= 0,3 => 30%0.03 /(0.03 + 0.01 + 0.06)= 0,3 => 30%これはPHPとは関係なく計算だけです –

+0

@ B001だから、これらの数字は変更することもできます。したがって、ユーザ1 = 1、ユーザ2 = 30、ユーザ3 = 0.01。それでも%を計算して、誰が勝つかを見てください。 –

+0

@LelioFaieta私はtitをmysqlデータベースから100%自動にします。 –

答えて

0

編集:この答えはタイトルに基づいており、 "PHP ...." ではないタグ "mysqlの"

各ユーザーは、n チケットを持っています。あなたのケースでは、10枚のチケットを持っているので、unelegantソリューションは、可能性が0と9の間の乱数を必要とする:

<?php 
$tickets = array(); 
$number_of_tickets = 0; 

foreach($users as $user) { 
    for($i = 0; i < $user->tickets; $i++) { 
     $tickets[] = $user->id; 
     $tickets++; 
    } 
} 

$lucky_draw = rand(0, $number_of_tickets); 
$winner = tickets[$lucky_draw] //ID of the user 

print("And the winner is...." . $winner); 
1

あなたは「加重確率分布」のように記述することができるか、技術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を選びます。

関連する問題