note 53600 modified in function.rand by danbrown

From: Date: Wed, 05 Nov 2008 15:38:12 +0000
Subject: note 53600 modified in function.rand by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-146172@lists.php.net to get a copy of this message
Lately I needed some random numbers with a gaussian (normal) distribution, not evenly distributed as the numbers generated by rand(). After googling a while, I found out that there is no perfect algrorithm that creates such numbers out of evenly distruted random numbers but a few methods that have similar effect. The following function implements all three algorithms I found- The the last two methods create numbers where you can find a lower and upper boundary and the first one will create a number from time to time (such as one in every 10000) that may be very far from the average value. Have fun testing and using it. <?php function gauss($algorithm = "polar") { $randmax = 9999; switch($algorithm) { //polar-methode by marsaglia case "polar": $v = 2; while ($v > 1) { $u1 = rand(0, $randmax) / $randmax; $u2 = rand(0, $randmax) / $randmax; $v = (2 * $u1 - 1) * (2 * $u1 - 1) + (2 * $u2 - 1) * (2 * $u2 - 1); } return (2* $u1 - 1) * (( -2 * log($v) / $v) ^ 0.5); // box-muller-method case "boxmuller": do { $u1 = rand(0, $randmax) / $randmax; $u2 = rand(0, $randmax) / $randmax; $x = sqrt(-2 * log($u1)) * cos(2 * pi() * $u2); } while (strval($x) == "1.#INF" or strval($x) == "-1.#INF"); // the check has to be done cause sometimes (1:10000) // values such as "1.#INF" occur and i dont know why return $x; // twelve random numbers case "zwoelfer": $sum = 0; for ($i = 0; $i < 12; $i++) { $sum += rand(0, $randmax) / $randmax; } return $sum; } } ?> --was-- Lately I needed some random numbers with a gaussian (normal) distribution, not evenly distributed as the numbers generated by rand(). After googling a while, I found out that there is no perfect algrorithm that creates such numbers out of evenly distruted random numbers but a few methods that have similar effect. The following function implements all three algorithms I found- The the last two methods create numbers where you can find a lower and upper boundary and the first one will create a number from time to time (such as one in every 10000) that may be very far from the average value. Have fun testing and using it. function gauss($algorithm = "polar") { $randmax = 9999; switch($algorithm) { //polar-methode by marsaglia case "polar": $v = 2; while ($v > 1) { $u1 = rand(0, $randmax) / $randmax; $u2 = rand(0, $randmax) / $randmax; $v = (2 * $u1 - 1) * (2 * $u1 - 1) + (2 * $u2 - 1) * (2 * $u2 - 1); } return (2* $u1 - 1) * (( -2 * log($v) / $v) ^ 0.5); // box-muller-method case "boxmuller": do { $u1 = rand(0, $randmax) / $randmax; $u2 = rand(0, $randmax) / $randmax; $x = sqrt(-2 * log($u1)) * cos(2 * pi() * $u2); } while (strval($x) == "1.#INF" or strval($x) == "-1.#INF"); // the check has to be done cause sometimes (1:10000) // values such as "1.#INF" occur and i dont know why return $x; // twelve random numbers case "zwoelfer": $sum = 0; for ($i = 0; $i < 12; $i++) { $sum += rand(0, $randmax) / $randmax; } return $sum; } } http://php.net/manual/en/function.rand.php

« previous php.notes (#146172) next »