PHPで下記のような確率で答えを求めたいのですが、こんなソースしか思いつきません。

何か良いアドバイスをお願いします。

【確率】
A:60%
B:20%
C:10%
D:7%
E:3%

【こんなソース】
$pro = rand(1, 100);

switch ($pro) {
case ($pro <= 60):
$ans = "A";
break;
case ($pro <= 80):
$ans = "B";
break;
case ($pro <= 90):
$ans = "C";
break;
case ($pro <= 97):
$ans = "D";
break;
default:
$and = "E";
}

回答の条件
  • 1人2回まで
  • 登録:2007/02/05 15:50:27
  • 終了:2007/02/05 20:26:48

ベストアンサー

id:Mook No.4

Mook回答回数1313ベストアンサー獲得回数3922007/02/05 17:55:14

ポイント25pt

ご自身で考えられた例で十分だと思いますが、

関数で実装したサンプルです。

<?
// -----------------------------------
// 出現確率の定義 : 合計が100でなくともOK
// -----------------------------------
$randArray = Array(
    "A"=> 60,
    "B"=> 20,
    "C"=> 10,
    "D"=> 7,
    "E"=> 3 );

// -----------------------------------
// 出現確率に応じて回答を返す関数
// -----------------------------------
function rndAnswer( $rndArray ) {
    $rndNum = rand(1, array_sum( $rndArray ) ); // 1 ~合計 の中で乱数を発生

    $subTotal = 0;
    foreach( $rndArray as $key => $num ) {
        $subTotal += $num;
        if ( $subTotal >= $rndNum ) {
            return $key;
        }
    }
}
// -----------------------------------
// 実際に100回実行してみるテスト
// -----------------------------------
print "RANDOM TEST<br>\n";
print '<table border="1">'."\n";
foreach( $randArray as $key => $num ) {
    $ansCount[$key] = 0;
}

for( $i=0 ; $i<10 ; $i++ ) {
    print "<tr>\n";
    for( $j=0 ; $j<10 ; $j++ ) {
        $ans = rndAnswer( $randArray );
        $ansCount[$ans]++;
        print "<td>$ans</td>\n";
        print "</td>\n";
    }
    print "</tr>\n";
}
print "</table>\n";
  // キー順にソート
ksort( $ansCount );
  // 回答の回数を表示
foreach( $randArray as $key => $num ) {
    print "$key({$num})... {$ansCount[$key]}回<br>\n";
}
?>

おまけで、実際の出現回数をテストするルーチンを実装しています。

F5 を押すごとに、テストできます。

その他の回答(3件)

id:ukiya No.1

ukiya回答回数4ベストアンサー獲得回数12007/02/05 16:14:14

ポイント23pt

こんな感じでは如何ですか。

$foo=array(
    "A" => 60,
    "B" => 20,
    "C" => 10,
    "D" => 7,
    "E" => 3,
);
$r = rand(1, 100);
foreach($foo as $k => $v){
    if($r<=$v){
        $ans=$k;
        break;
    }
    $r-=$v;
}
echo $ans;

配列に確率が大きい順に値を格納するのが高速化のポイントです。

id:takfjt No.2

takfjt回答回数23ベストアンサー獲得回数32007/02/05 16:30:51

ポイント23pt

こんな感じでしょうか

$p = array(
        array("kakuritu"=>60, "output"=>"A"),
        array("kakuritu"=>20, "output"=>"B"),
        array("kakuritu"=>10, "output"=>"C"),
        array("kakuritu"=>7,  "output"=>"D"),
        array("kakuritu"=>3,  "output"=>"E")
);

$pro = rand(1, 100);

for ($i = 0, $sum = 0; $i < count($p); $i++) {
        $kakuritu = $p[$i]["kakuritu"] + $sum;
        if ($pro <= $kakuritu) {
                $ans = $p[$i]["output"];
                break;
        }
        $sum += $p[$i]["kakuritu"];
}
id:tezcello No.3

tezcello回答回数460ベストアンサー獲得回数692007/02/05 17:41:45

ポイント23pt
$answers = array('A'=>'60', 'B'=>'20', 'C'=>'10', 'D'=>'7', 'E'=>'3');
$i = rand(1, 100);
$j = 0;
foreach ($answers as $key=>$val){
    $j += $val;
    if ($i <= $j) {
        $ans = $key;
        break;
    }
}

僕もこんなのしか思いつきませんが。

id:Mook No.4

Mook回答回数1313ベストアンサー獲得回数3922007/02/05 17:55:14ここでベストアンサー

ポイント25pt

ご自身で考えられた例で十分だと思いますが、

関数で実装したサンプルです。

<?
// -----------------------------------
// 出現確率の定義 : 合計が100でなくともOK
// -----------------------------------
$randArray = Array(
    "A"=> 60,
    "B"=> 20,
    "C"=> 10,
    "D"=> 7,
    "E"=> 3 );

// -----------------------------------
// 出現確率に応じて回答を返す関数
// -----------------------------------
function rndAnswer( $rndArray ) {
    $rndNum = rand(1, array_sum( $rndArray ) ); // 1 ~合計 の中で乱数を発生

    $subTotal = 0;
    foreach( $rndArray as $key => $num ) {
        $subTotal += $num;
        if ( $subTotal >= $rndNum ) {
            return $key;
        }
    }
}
// -----------------------------------
// 実際に100回実行してみるテスト
// -----------------------------------
print "RANDOM TEST<br>\n";
print '<table border="1">'."\n";
foreach( $randArray as $key => $num ) {
    $ansCount[$key] = 0;
}

for( $i=0 ; $i<10 ; $i++ ) {
    print "<tr>\n";
    for( $j=0 ; $j<10 ; $j++ ) {
        $ans = rndAnswer( $randArray );
        $ansCount[$ans]++;
        print "<td>$ans</td>\n";
        print "</td>\n";
    }
    print "</tr>\n";
}
print "</table>\n";
  // キー順にソート
ksort( $ansCount );
  // 回答の回数を表示
foreach( $randArray as $key => $num ) {
    print "$key({$num})... {$ansCount[$key]}回<br>\n";
}
?>

おまけで、実際の出現回数をテストするルーチンを実装しています。

F5 を押すごとに、テストできます。

  • id:atoly
    大変、勉強になりました。
    みなさま、ありがとうございます!!
  • id:Mook
    回答を見直してみたら、途中で修正したゴミがちらほらと・・・。

    --------
    print "</td>\n";
    --------
    は不要です。
    --------
    // キー順にソート
    ksort( $ansCount );
    --------
    も不要です。

    失礼しました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません