PHP Zufallszahlen aus negativen Zahlen oder Kommazahlen
Um es direkt vorweg zu sagen: die Nutzung von mt_rand() oder wenn nötig auch rand() ist auf jeden Fall schneller. Allerdings ist es bei mir schon häufiger vorgekommen, dass ich Zufallszahlen benötigt habe, die keine ganzen Zahlen oder nicht positiv waren.
Für die Nutzung von negativen Zahlen ist die einfachste Variante einen Wert zu addieren und später wieder abzuziehen:
[pastacode lang=“php“ message=“PHP“ highlight=““ provider=“manual“]
$a = -100;
$b = -20;
$a += 100;
$b += 100;
$num = mt_rand($a, $b);
$num -= 100;
[/pastacode]
Das funktioniert natürlich auch, wenn man nicht weiß, welchen Wert $a hat, indem man einfach $a zwischenspeichert und diesen Wert abzieht (er ist ja negativ) und später wieder addiert.
[pastacode lang=“php“ message=“PHP“ highlight=““ provider=“manual“]
$a = -100;
$b = -20;
$sub = $a;
$a -= $sub;
$b -= $sub;
$num = mt_rand($a, $b);
$num += $sub;
[/pastacode]
Bei Kommazahlen ist das Ganze schon schwieriger. Die einfachste Variante hierbei ist eine maximale Anzahl an Kommastellen festzulegen (ich nehme hierbei 5).
[pastacode lang=“php“ message=“PHP“ highlight=““ provider=“manual“]
$a = 0.234534;
$b = 12.7;
$multi = pow(10, 5); // Anzahl Kommastellen
$num = mt_rand(round($a * $multi), round($b * $multi)) / $multi;
[/pastacode]
Zuerst wird der Multiplikator festgelegt, in diesem Fall für 5 Kommastellen, so dass aus 0.234534 danach 23453.4 wird und aus 12.7 wird 1270000. Aus diesem Bereich wird nun eine Zufallszahl gezogen. Dabei wird die 6. Kommastelle der ersten Zahl vorher abgeschnitten bzw. weggerundet. Die entstandene Zufallszahl (z. B. 10443) wird nun wieder dividiert und man hat das gewünschte Ergebnis 0.10443
Es gibt auch die Möglichkeit die Anzahl der Kommastellen automatisch zu berechnen, ich würde davon aber abraten, da es sehr langsam ist. Hierbei wird der Multiplikator nicht wie vorher festgelegt, sondern ausgerechnet:
[pastacode lang=“php“ message=“PHP“ highlight=““ provider=“manual“]
$multi = 1;
if(intval($a) != $a) {
$tmp = $a - intval($a);
$tmp = pow(10, strlen($tmp) - 2);
if($tmp > $multi) $multi = $tmp;
}
if(intval($b) != $b) {
$tmp = $b - intval($b);
$tmp = pow(10, strlen($tmp) - 2);
if($tmp > $multi) $multi = $tmp;
}
[/pastacode]
Ich habe wie gesagt diese Methode nicht verwendet, da sie etwa doppelt so lange benötigt wie ein fester Multiplikator.
Hier nun noch meine komplette get_random Funktion:
[pastacode lang=“php“ message=“PHP“ highlight=““ provider=“manual“]
function get_random($min, $max, $round_to = 5) {
if($min > $max) {
$tmp = $min;
$min = $max;
$max = $tmp;
}
$sub = 0;
if($min < 0) {
$sub = $min;
$min -= $sub;
$max -= $sub;
}
if(intval($min) != $min || intval($max) != $max) {
$multi = pow(10, $round_to);
$num = mt_rand(round($min * $multi), round($max * $multi)) / $multi;
} else {
$num = mt_rand($min, $max);
}
$num += $sub;
return $num;
}
[/pastacode]
Diese Funktion funktioniert mit negativen Zahlen, Kommazahlen und auch mit vertauschten Werten. Ich würde aber dringend dazu raten sie nur zu verwenden, wenn es notwendig ist und bei normalen positiven ganzen Zahlen immer mt_rand zu nutzen.
Beachtet auch unbedingt, dass die Angabe des Parameters $round_to entscheidet, in welchen Schritten die Zufallszahlen liegen. get_random(0.1, 0.5, 5) gibt also auch 0.23643 zurück. Wenn ihr dabei wirklich nur 0.1er Schritte möchtet müsst ihr auch get_random(0.1, 0.5, 1) verwenden.
Kommazahlen: Nimm eine beliebige Primzahl, und teil sie durch einen per mt_rand() ermittelten wert.
Negative Zahlen: Ermittle einen Wert mit mt_rand() und multipliziere ihn mit -1.
Wo ist das Problem?
Das ist nicht ganz korrekt.
Mit der Methode würde es keine Zufallszahl zwischen -10 und 10 zum Beispiel geben.
Bei der Verwendung von Teilern gibt es das Problem, dass die Zufallszahlen nicht gleichmäßig verteilt sind.
Mit negativen Zahlen scheint das Skript Probleme zu haben habe einen bereich von -0.3 bis 0.3 angegeben und bekomme dann als Ergebnisse die sogar größer als 0.3 sind, dass kann ja nicht wirklich stimmen.
Hallo und Danke für den Hinweis…
Komisch, dass das noch niemandem aufgefallen ist, natürlich muss es in der vorletzten Codezeile heißen += und nicht -=
Habe ich nun korrigiert.