IT系のネタ中心 チャレンジしたことやつまづいたことを載せたいと思います このブログのコンセプトは"ハッキングの為なら愛する家族を傷つけることをいとわない" ハッカー(ホワイト)を目指しているとっとこ駆け出しエンジニアです
/** * ルーレットクラス */ class Roulette { const RAND_MIN = 1; const RAND_MAX = 1000; // 賞 const PRIZE_1 = 1; const PRIZE_2 = 2; const PRIZE_3 = 3; const PRIZE_4 = 4; const PRIZE_5 = 5; // RAND_MAXあたりの賞を貰える人の割合 private $_prize_user_nums = [ self::PRIZE_1 => 1, self::PRIZE_2 => 30, self::PRIZE_3 => 100, self::PRIZE_4 => 300, ]; /** * ルーレット用の乱数を生成する * * @return int 乱数 */ protected function generateRand() { return mt_rand(self::RAND_MIN, self::RAND_MAX); } /** * ルーレットを回して、賞を返す * * @return int 賞 */ public function elect() { $rand = $this->generateRand(); if ($rand < 1) { return self::PRIZE_5; } $sum_prize_user_num = 0; $sumPrizeUserCount = function ($prize_user_num) use (&$sum_prize_user_num){ $sum_prize_user_num += $prize_user_num; return $sum_prize_user_num; }; if ($rand <= $sumPrizeUserCount($this->_prize_user_nums[self::PRIZE_1])) { return self::PRIZE_1; } elseif ($rand <= $sumPrizeUserCount($this->_prize_user_nums[self::PRIZE_2])) { return self::PRIZE_2; } elseif ($rand <= $sumPrizeUserCount($this->_prize_user_nums[self::PRIZE_3])) { return self::PRIZE_3; } elseif ($rand <= $sumPrizeUserCount($this->_prize_user_nums[self::PRIZE_4])) { return self::PRIZE_4; } return self::PRIZE_5; } }
require_once 'Roulette.php'; /** * ルーレットテストクラス */ class RouletteTest extends PHPUnit_Framework_TestCase { public function providerPrizePattern() { return [ [Roulette::PRIZE_1, 1, '1を1等とする'], [Roulette::PRIZE_2, 2, '2~31を2等とする'], [Roulette::PRIZE_2, 31, '2~31を2等とする'], [Roulette::PRIZE_3, 32, '32~131を3等とする'], [Roulette::PRIZE_3, 131, '32~131を3等とする'], [Roulette::PRIZE_4, 132, '132~431を4等とする'], [Roulette::PRIZE_4, 431, '132~431を4等とする'], [Roulette::PRIZE_5, 432, '432以上は5等とする'], [Roulette::PRIZE_5, 1000, '432以上は5等とする'], [Roulette::PRIZE_5, 1001, '1001以上も5等とする'], [Roulette::PRIZE_5, 0, '0は5等とする'], [Roulette::PRIZE_5, -1, '負数は5等とする'], ]; } /** * @test * @dataProvider providerPrizePattern */ public function 確率に応じて等が返ること($expected_prize, $rand) { $roulette_mock = Phake::partialMock('Roulette'); Phake::when($roulette_mock)->generateRand()->thenReturn($rand); $this->assertSame($expected_prize, $roulette_mock->elect()); } /** * @test */ public function 賞の確率による平均が標準偏差3つ分の誤差の範囲内であること() { $roulette = new Roulette(); $prizes = []; $prizes[$roulette::PRIZE_1] = 0; $prizes[$roulette::PRIZE_2] = 0; $prizes[$roulette::PRIZE_3] = 0; $prizes[$roulette::PRIZE_4] = 0; $prizes[$roulette::PRIZE_5] = 0; $n = 10000; for ($i = 0;$i < $n; $i++) { $prize = $roulette->elect(); $prizes[$prize]++; } // 標準偏差の数 $times = 3; // n * p = 平均, x = 計測値, メッセージ, 標準偏差 sqrt($n * $p * (1 - $p))の三倍 99.7%の確率で収まる // p = 0.001 $x = $prizes[$roulette::PRIZE_1]; $this->assertEquals(10, $x, '1等 99.7%の確率で成功するテスト', $times * 3.1606961258558); // p = 0.03 $x = $prizes[$roulette::PRIZE_2]; $this->assertEquals(300, $x, '2等 99.7%の確率で成功するテスト', $times * 17.058722109232); // p = 0.1 $x = $prizes[$roulette::PRIZE_3]; $this->assertEquals(1000, $x, '3等 99.7%の確率で成功するテスト', $times * 30); // p = 0.3 $x = $prizes[$roulette::PRIZE_4]; $this->assertEquals(3000, $x, '4等 99.7%の確率で成功するテスト', $times * 45.825756949558); // p = 0.569 $x = $prizes[$roulette::PRIZE_5]; $this->assertEquals(5690, $x, '5等 99.7%の確率で成功するテスト', $times * 49.521611443894); } }
0 件のコメント :
コメントを投稿