From: theultramage at gmail dot com Operating system: Windows/FreeBSD PHP version: 5.2.9 PHP Bug Type: Arrays related Bug description: array_rand broken sorting semantics
Description: ------------ The code of PHP_FUNCTION(array_rand) contains a conditional call to array_data_shuffle ('shuffle()' function). It was added in http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.79&r2=1.80& to resolve bug http://bugs.php.net/bug.php?id=7492 . There are several mistakes here: 1. The developer used the comparison (num_req_val == num_avail). However, these are not constants and change a lot during the execution of the algorithm. While it is true that the check holds true in the case where the user requests all elements in the array, it also holds true in the general case where both of these variables reach the value '0' at the end of the loop, which is 10+% of the time and occurs randomly. This causes array_rand to produce sequences that are "in ascending order, but sometimes completely random". See http://php.net/manual/en/function.array-rand.php#74406. 2. The developer should have never made this change in the first place. The user's complaint was "If I ask array_rand() to pick 6 elements out of 6, the result isn't randomized". But here the user failed to realize that it's not array_rand's job to produce the results randomly ordered. It's to "pick K random entries out of N". Therefore the change 1.80 was out of scope of what array_rand was intended for. The developer should have instead instructed the user to use shuffle() on the result if he required a shuffled result. My proposal: Remove the two lines that do the shuffling in array_rand's code, since they're broken and don't make sense even if they were fixed. It's not the function's task to randomize the output's order - that should be done by the user if he needs to do so. PS: A more detailed analysis can be found at http://netvor.sk/~umage/wtf/www/php/array_rand.html . Reproduce code: --------------- <?php // also see http://php.net/manual/en/function.array-rand.php#74406 // test case for '3 out of 10'... try this and then try '8 out of 10' $n = 20; $a = array(0,1,2,3,4,5,6,7,8,9); for( $i = 0; $i < $n; $i++ ) { $keys = array_rand($a,3); printf("%d %d %d\n", $keys[0], $keys[1], $keys[2]); } ?> Expected result: ---------------- Individual sequences should appear in ascending order, since that's how the original code generated them. Actual result: -------------- The sequences are mostly sorted, sometimes shuffled. This occurs randomly on each run. The percentage of shuffled sequences increases as the requested number nears the number of entries in the array. -- Edit bug report at http://bugs.php.net/?id=48224&edit=1 -- Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=48224&r=trysnapshot52 Try a CVS snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=48224&r=trysnapshot53 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=48224&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=48224&r=fixedcvs Fixed in CVS and need be documented: http://bugs.php.net/fix.php?id=48224&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=48224&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=48224&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=48224&r=needscript Try newer version: http://bugs.php.net/fix.php?id=48224&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=48224&r=support Expected behavior: http://bugs.php.net/fix.php?id=48224&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=48224&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=48224&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=48224&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=48224&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=48224&r=dst IIS Stability: http://bugs.php.net/fix.php?id=48224&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=48224&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=48224&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=48224&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=48224&r=mysqlcfg