note 96022 deleted from function.mt-rand by salathe

From: Date: Fri, 07 Nov 2014 11:02:52 +0000
Subject: note 96022 deleted from function.mt-rand by salathe
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-200816@lists.php.net to get a copy of this message
Note Submitter: ISAWHIM ---- This is not trying to dissuade use of this alternative, just trying to expand on the things to "watch-out-for", when using this... As per the description assumption... "Many random number generators of older libcs have dubious or unknown characteristics and are slow." You would elude to the assumption that mt_rand() does not have, "dubious or unknown characteristics". It is obvious that it is faster, but that does not count the additional code required to ensure validity of results, or scope of input value checking. This function fails horribly, without error, when operating out of the scope of the range. (Key point being, "without error".) mt_getrandmax() is NOT the max INTEGER size. It is limited to positive numbers from ZERO to your integers largest value. Thus, it is HALF the size of an INTEGER, since integers are SIGNED, but mt_rand can only correctly randomize from ZERO to mt_getrandmax(). (Though, that is not entirely true. It can do negative numbers, if the min/max range/spread is not greater than the value of mt_getrandmax()... sometimes.) Things to watch-out for... (Sort of negates any speed gains.) This assumes you "Attempted" to process MIN>=0 and MAX<=mt_getrandmax(). Returning a negative value = RANDOMIZER FAILED Returning a vlaue higher than mt_getrandmax() = RANDOMIZER FAILED Returning SAME_NUMBER from more than one call = Possibly RANDOMIZER FAILED Returning a number <MIN or >MAX = RANDOMIZER FAILED PHP version 5.2.6 on Apechee 2.0.63 on a Linux server. Specific instances of failure... (All these still return a value.) With RAND_MAX reporting that it is '2147483647'. <?PHP // Returns negative numbers as if (-2147483647,0) $z = mt_rand(0,2147483648); // Returns mostly 1 or negative numbers $z = mt_rand(-2147483647,2147483647); // Returns negative numbers, but within range set??? // So much for returning only values from 0 to Max $z = mt_rand(-2147483647,0); // Attempt to stay within the range/spread of mt_getrandmax() // Results are odd, like 180 to 2147478000 $z = mt_rand(2147483647,4294967294); // Works, but it should not, as the value is not an INT // Values are converted to floor(x), so range is (0,0) $z = mt_rand(0.000001,0.9999999); ?> Code used to test... <?PHP // Reports the MAX possible, which is half of an INT's value echo('RAND_MAX: '.mt_getrandmax()); for($i=0;$i<=100000;$i++) { // RAND_MAX = 2147483647 $z = mt_rand(0,2147483647); // echo($z.'<BR>'); // Uncomment to see results, lower LOOP values first! if($z>$high || !isset($high)){$high=$z;} if($z<$low || !isset($low)){$low=$z;} } echo('HIGH: '.$high.'<BR>LOW: '.$low.'<BR>'); ?> To get a number that is actually in the full range of an INT, you need to make two separate calls, and add them together. Then convert that unsigned INT value into a signed INT value.

« previous php.notes (#200816) next »