|
|
mt_srand (PHP 3 >= 3.0.6, PHP 4, PHP 5) mt_srand -- Seed the better random number generator Descriptionvoid mt_srand ( [int seed] )
Seeds the random number generator with
seed.
Since PHP 4.2.0, the seed
becomes optional and defaults to a random value if omitted.
Пример 1. mt_srand() example |
<?php
function make_seed()
{
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
mt_srand(make_seed());
$randval = mt_rand();
?>
|
|
Замечание: Начиная с PHP 4.2.0, больше нет
необходимости инициализировать генератор случайных чисел функциями
srand() или mt_srand(), поскольку
теперь это происходит автоматически.
See also:
mt_rand(),
mt_getrandmax(), and
srand().
Joe
03-Sep-2007 04:59
In some cases it is necessary to be able to create same sequence of pseudo-random numbers. E.g. to run repeatable simulation run with different parameters. Since php 5.2.1 it is not possible even using same seed in mt_srand function. For such cases use srand instead.
Kapr
14-Jun-2007 10:25
To slonmron:
Seed for random numbers generator should be initialized only once, before calling proper rand function. After that you give pseudorandom sequence by multiple calling rand. Initialization of random seed is used if 1) You have better source of random seed than implemented algorithm or 2) if You need always the same sequence of pseudorandom numbers. Example given by You shows only that first rand result strongly depends on seed, what is by definition. It is not a bug.
slonmron_no_spam_please_ at yahoo dot com
16-Mar-2007 12:44
Looks like mt_rand() gives same result for different seeds when the lowest bits are different only. Try this:
#!/usr/bin/php -q
<?php
$min = -17;
$max = $min + 48; for ($testseed=$min; $testseed<$max; $testseed++)
{
mt_srand( $testseed );
$r = mt_rand();
printf("mt_srand( 0x%08x ): mt_rand() == 0x%08x == %d\n", $testseed, $r, $r);
}
?>
This is a snapshop of the results:
...
mt_srand( 0xfffffffc ): mt_rand() == 0x0a223d97 == 170016151
mt_srand( 0xfffffffd ): mt_rand() == 0x0a223d97 == 170016151
mt_srand( 0xfffffffe ): mt_rand() == 0x350a9509 == 889885961
mt_srand( 0xffffffff ): mt_rand() == 0x350a9509 == 889885961
mt_srand( 0x00000000 ): mt_rand() == 0x71228443 == 1898087491
mt_srand( 0x00000001 ): mt_rand() == 0x71228443 == 1898087491
mt_srand( 0x00000002 ): mt_rand() == 0x4e0a2cdd == 1309289693
mt_srand( 0x00000003 ): mt_rand() == 0x4e0a2cdd == 1309289693
...
I found this occationally. I have no idea if it is a bug or not. In my real life I do not intend to use sequentional seeds. However, probably this may be important for somebody.
oxai NOSPAM post dot htnet dot hr
09-Sep-2006 11:14
try this instead(!):
<?php
function randomizeProcessSeed()
{
static $thisProcessHasBeenInitialized;
if( $thisProcessHasBeenInitialized ) return;
list($usec, $sec) = explode(' ', microtime());
mt_srand( (10000000000 * (float)$usec) ^ (float)$sec );
$thisProcessHasBeenInitialized = true;
} randomizeProcessSeed();
?>
gigs
12-Jan-2006 11:13
used the little script from mrcheezy at hotmail dot com and got much better results using
mt_srand(crc32(microtime()));
vbassassin at coderheaven dot com
30-Nov-2005 08:57
"Better still: Use a 31-bit hash of microtime() as the seed. "
Correct me if i am wrong, but woudlnt using microtime() still limit the total seeds to 1,000,000 again? Since the 31-bit hash will always give the same hash for the same number, and in the microtime() function you could have 1,000,000 or less numbers. So in effect your still no better off at all :-p
Best regards,
scott
PS: I actually agree that PHP has pretty much resolved the issue and got as close as anyones going to get to solving the seeding issue by introducing the "Mersenne Twister" algorithm which creates a much larger pool than 1,000,000 numbers. Just because the mt_srand() function exists doesnt mean you HAVE to use it ;-) use it if you NEED a specific list of the same numbers (comes in handy for encryptions with passwords ;-)
12-Sep-2005 06:03
It's better to use the following method instead of the one in the documentation metioned:
<?php
mt_srand((double)(microtime() ^ posix_getpid()));
?>
Otherwise people requesting the script at the same time could get the same generated number.
Schrecktech
20-Jan-2005 06:16
::: My seeding report :::
For FreeBSD 4.8-STABLE PHP 4.3.10 it was good enough and faster to not seed at all...although I did not test the random pseudo terminal.
In detail only seeding once by a previous seed using the hex version (case 3 below) for larger numbers and longer run times faired the best. For small numbers it was better to not seed at all (let alone faster). Play with the $loop and $max numbers to see...
<?
function get_a_good_seed
(
$choice = 3
)
{
static $seed;
$seed = 0;
switch($choice)
{
case 1:
// from php.net documentation.
list($usec, $sec) = explode(' ', microtime());
$seed = (float) $sec + ((float) $usec * 1000000);
break;
case 2:
// from high primary number.
$seed = (double)microtime()*1000003;
break;
case 3:
// from a good random source.
$seed = hexdec(substr(md5(microtime()), -8)) & 0x7fffffff;
break;
case 4:
// from random terminal
// NOT TESTED
break;
default:
break;
}
return($seed);
}
function load_last_random
(
)
{
static $last;
static $handle;
// NOTE: create this file with a random integer...
$handle = fopen("random.txt", "r");
while (!feof($handle)) {
$last = fgets($handle, 4096);
}
fclose($handle);
return($last);
}
function save_last_random
(
$save = 0
)
{
$handle = fopen("random.txt", "w");
fwrite($handle, $save);
fclose($handle);
}
function seed_random_number_generator
(
$type = 3,
$ignore_generated_already = FALSE
)
{
static $generator_seeded = FALSE;
if($ignore_generated_already || !$generator_seeded)
{
// 1) load last with time...force integer.
// 2) generate a new random seed and save for next time...
mt_srand(( load_last_random()+get_a_good_seed($type) ) & 0x7fffffff);
save_last_random(mt_rand());
$generator_seeded= TRUE;
}
}
?>
fasaxc at yahoo dot co dot uk
25-Jul-2003 08:01
In fact, here's an even better function than the one below assuming your install provides a random entropy daemon and you're running *nix (to check for the former type "head -c 6 /dev/urandom" on the command line if available - if you get 6 random characters you're set). N.B. php must be able to find the head program so it must be in your path and allowed if you're running safe mode.
The functions db_set_global() and db_get_global() I use to set/get a variable from a central database but you could save/restore the variable from a file instead or just use the function get_random_word().
<?
####################################
## returns a random 32bit integer.
## Passing a parameter of True gives a better random
## number but relies on the /dev/random device
## which can block for a long time while it gathers
## enough random data ie. DONT USE IT unless
## a) You have an entropy generator attatched to
## your computer set to /dev/random -OR-
## b) Your script is running locally and generating
## a good random number is very important
####################################
function get_random_word($force_random=False) {
if ($force_random) {
$u='';
} else {
$u='u';
}
$ran_string=shell_exec("head -c 4 /dev/{$u}random");
$random=ord(substr($ran_string,0,1))<<24 |
ord(substr($ran_string,1,1))<<16 |
ord(substr($ran_string,2,1))<<8 |
ord(substr($ran_string,3,1));
return $random;
}
--EITHER - IF YOU'VE SET UP A DATABASE OF GLOBAL VARIABLES--
## If the seed is found in the database
if ($seed=db_get_global('seed')) {
# use mt_rand() to get the next seed
mt_srand($seed);
# then XOR that with a random word
$seed=(mt_rand() ^ get_random_word());
} else {
## Make a completely new seed (First Run)
# Generate the seed as a proper random no using /dev/random
$seed=get_random_word(True);
mt_srand($seed);
}
db_set_global('seed',$seed);
--OR JUST--
mt_srand(get_random_word());
?>
fasaxc at yahoo dot com
17-Jul-2003 04:14
The best way to ensure a random seed is to do the following:
To start:
1) get your initial seed with mt_srand(microtime() * 1000000)
2) generate a random no. $random=mt_rand()
3) save this number in a file (or database or whatever so that it is available next time the page is loaded)
Now, for each time your script is loaded :
1) load the value you saved above and do $new_seed=($random+(microtime() * 1000000))%pow(2,32)
2) mt_srand($new_seed);
3) generate a new random no. $random=mt_rand()
4) save that number back in the file/database
This procedure takes advantage not only of the randomness of microtime() but of all the previous calls to microtime() so your seed becomes better and better with time. It also generates good seeds even on platforms where microtime() doesn't take all the values it can.
Just using microtime() * 1000000 only results in 1000000 possible seeds (and less on some platforms as noted) - the function above gives 2^32 seeds with an avelanche effect accross multiple executions.
mrcheezy at hotmail dot com
17-Feb-2003 02:14
Very good points above on seeds, thank you. If you would like to test a seed try using the code below. It will take between 5 and 20 seconds depending on your system and then will spit out the number of reused keys out of 100,000 attempts.
; for ($i=0; $i<100000; $i++) {
; mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
; $rand = mt_rand();
;
; ($arr[$rand] == '1') ? $k++ : $arr[$rand] = '1';
; }
mattb at columbia dot edu
12-Dec-2002 12:54
This is effectively the same thing, but it uses a more efficient bit mask instead of a substring. Here's the verbose version:
function mkseed()
{
$hash = md5(microtime());
$loWord = substr($hash, -8);
$seed = hexdec($loWord);
$seed &= 0x7fffffff;
return $seed;
}
Or, if you're a real hacker, this is a more concise version:
function mkseed()
{
return hexdec(substr(md5(microtime()), -8)) & 0x7fffffff;
}
Note, the range on the md5 sum is really arbitrary. You could use whatever portion you like, just so long as it's 32 bits.
Now just call mt_srand() (once) as follows:
mt_srand(mkseed());
Of course, unless you wanted the mkseed() function for something else, you could skip all that jive and just do this somewhere in a global include file:
<?php
if (!isset($_MyApp_MtSrand)
|| !$_MyApp_MtSrand)
{
$_MyApp_MtSrand = true;
mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
}
?>
ghaecker_no_spam at idworld dot net
21-Sep-2002 01:20
The range of unique seeds using this method is a bit over 2 billion. This approach also prevents re-seeding.
function seed_mt_rand() {
|
|