Im Internet gibt es viele Beiträge und Diskussionen zum Thema rand() und mt_rand(). Beides sind Funktionen die PHP bereitstellt um Zufallszahlen zu erzeugen.
mt_rand() arbeitet nach dem Prinzip des Mersenne-Twisters der „bessere Zufallszahlen“ erzeugen soll als die bisherige Implementation der rand()-Funktion. Es kursieren auch noch Angaben, dass dieser Algorithmus laut PHP-Manual bis zu vier mal schneller sein soll als rand().
In diesem Artikel beleuchte ich mit unterschiedlichen Methoden die Facetten der beiden Algorithmen. Es handelt sich dabei um eine dynamisch erzeugte Seite, sollte sich die Implementation ändern, so kann es sein, dass komplett andere Fakten vorliegen als zum Zeitpunkt als dieser Artikel geschrieben wurde.
Die Ladezeit der Seite wird im Normalfall etwas länger dauern als bei normalen Seiten.

Zunächst ein Auszug aus dem PHP-Manual:

mt_rand — Erzeugt „bessere“ Zufallszahlen
Viele Zufallszahlengeneratoren, die auf älteren libc-Versionen basieren, haben seltsame oder doch zumindest unerwartete Verhaltensweisen und sind zudem recht langsam. Standardmäßig verwendet PHP den libc-Zufallszahlengenerator mit der Funktion rand(). Die Funktion mt_rand() kann jedoch als vollwertiger Ersatz verwendet werden. Sie verwendet einen Zufallszahlengenerator mit den bekannten Charakteristika der » Mersenne Twister, die Zufallszahlen viermal schneller generiert als der durchschnittliche libc-rand()-Aufruf.

Wenn die Funktion ohne Angabe von min und/oder max aufgerufen, gibt mt_rand() eine Pseudozufallszahl zwischen 0 und mt_getrandmax() zurück. Benötigen Sie zum Beispiel eine Zufallszahl zwischen 5 und 15 (inklusive), verwenden Sie mt_rand(5, 15).

(Quelle: PHP Manual)

Und für rand():

rand — Erzeugt einen zufälligen Integerwert
Liefert eine Pseudozufallszahl zwischen min und max (inklusive), oder zwischen 0 und get_randmax() falls keine Parameter angegeben wurden. Wenn Sie z.B. einen Zufallswert zwischen 5 und 15 benötigen so wäre der Aufruf dafür rand(5, 15).

Hinweis: Auf manchen Plattformen (Windows z.B.) ist get_randmax() nur 32768. Wenn sie einen größeren Wertebereich benötigen sollten, so können Sie entweder einen größeren max-Wert übergeben oder besser die mt_rand()-Funktion anstelle von rand() einsetzen.

Hinweis: Seit PHP 4.2.0 besteht keine Notwendigkeit mehr, den Zufallsgenerator für Zahlen mit srand() oder mt_srand() zu füttern, das geschieht nun automatisch.

(Quelle: PHP Manual)

Wie man sieht, steht hier nichts mehr von einem Geschwindigkeitsvorteil. Einzig das „bessere Zufallszahlen“ scheint auf einen Unterschied zwischen den beiden Generatoren hinzuweisen. Auch scheint bei mt_rand() keine Begrenzung auf einen Wert von 32768 (2^15) vorzuliegen.

Im folgenden soll ein wenig dargestellt werden, ob Unterschiede beispielsweise in der Zufälligkeit vorliegen oder ob eine Variante einen deutlichen Geschwindigkeitsvorteil aufweisen kann.
Eine interessante Variante die Zufälligkeit visuell darzustellen fand ich auf der Seite Dog-Net.org auf der Seite kann man sehen, dass die Verwendung von rand() im Gegensatz zu mt_rand() ein deutliches Muster in einem Bild erzeugt. Demnach können keine wirklich zufälligen Zufallszahlen vorliegen.
Ich habe diese Variante auf meinen Blog portiert, kann aber keine nachvollziehbaren Muster erkennen. Falls jemand doch mal eines sieht, das Bild gleich irgendwohin abspeichern, es wird bei jedem Aufruf der Seite neu erzeugt. Falls jemand Interesse an meinem PHP-Code hat kann ich ihn gerne zukommen lassen.

Mit mt_rand():

Mit rand():

Nun nachdem dieser Test keine augenscheinlichen Schwächen mehr aufweist, noch ein Geschwindigkeitstest und eine kleine Auswertung der erzeugten Nummern:

Bei der Ausführungsgeschwindigkeit konnte ich Unregelmäßigkeiten feststellen, manchmal liegt mt_rand() vorn, manchmal rand(). Ich vermute, dass durch die relativ lange Ausführzeit ein Taskswitch vorgenommen wird und so teilweise Zeit zur Erzeugung gerechnet wird, welche effektiv gar nicht in diesem Skript verbracht wird. Daher eine zweite Variante:

15000 mal 20 Zufallszahlen generiert in 30.791997909546 Millisekunden mit rand(); 15000 mal 20 Zufallszahlen generiert in 24.245500564575 Millisekunden mit mt_rand();


Ich würde eher mt_rand() benutzen, weil hier auf jeden Fall keine Beschränkung auf dem Maximalwert liegt. Ansonsten scheint es zumindest in der PHP version 5.2.6 keine wesentlichen Unterschiede zwischen den beiden Funktionen geben.
Natürlich lässt sich auch bei dieser Variante nicht ausschließen, dass ein Taskswitch auftritt, auch sind Zweifel an der Genauigkeit der Messung durchaus gerechtfertigt, da zumindest unter Windows eine Zeitmessung unter einer Millisekunde nicht ohne weiteres möglich ist, und ich gewisse Zweifel hege, dass die Zeitmessung in PHP diese Genauigkeit aufweist.
Aber es sieht meistens so aus, als würden beide Varianten in Sachen Geschwindigkeit und auch der Zufälligkeit gleich auf liegen.

Die Diagramme werden übrigens mit HTML-Graphs erzeugt (die Navigation befindet sich am unteren Rand der Webseite).