Comment générer un float aléatoire compris entre 0 et 1 en PHP?
Je recherche l'équivalent PHP de Math.random()
de Java.
Vous pouvez utiliser la fonction standard: lcg_value () .
Voici une autre fonction donnée sur le Rand () docs:
// auxiliary function
// returns random number with flat distribution from 0 to 1
function random_0_1()
{
return (float)Rand() / (float)getrandmax();
}
Exemple de documentation:
function random_float ($min,$max) {
return ($min+lcg_value()*(abs($max-$min)));
}
update: oubliez cette réponse ça ne marche pas avec php -v> 5.3
Qu'en est-il de
floatVal('0.'.Rand(1, 9));
?
cela fonctionne parfaitement pour moi, et ce n'est pas seulement pour 0 - 1 par exemple entre 1.0 - 15.0
floatVal(Rand(1, 15).'.'.Rand(1, 9));
class SomeHelper
{
/**
* Generate random float number.
*
* @param float|int $min
* @param float|int $max
* @return float
*/
public static function Rand($min = 0, $max = 1)
{
return ($min + ($max - $min) * (mt_Rand() / mt_getrandmax()));
}
}
function mt_Rand_float($min, $max, $countZero = '0') {
$countZero = +('1'.$countZero);
$min = floor($min*$countZero);
$max = floor($max*$countZero);
$Rand = mt_Rand($min, $max) / $countZero;
return $Rand;
}
Exemple:
echo mt_Rand_float(0, 1);
résultat: 0.2
echo mt_Rand_float(3.2, 3.23, '000');
résultat: 3.219
echo mt_Rand_float(1, 5, '00');
résultat: 4.52
echo mt_Rand_float(0.56789, 1, '00');
résultat: 0.69
Rand(0,1000)/1000 returns:
0.348 0.716 0.251 0.459 0.893 0.867 0.058 0.955 0.644 0.246 0.292
ou utilisez un plus grand nombre si vous voulez plus de chiffres après la virgule décimale
$random_number = Rand(1,10).".".Rand(1,9);
function frand($min, $max, $decimals = 0) {
$scale = pow(10, $decimals);
return mt_Rand($min * $scale, $max * $scale) / $scale;
}
echo "frand(0, 10, 2) = " . frand(0, 10, 2) . "\n";
La plupart des réponses utilisent mt_Rand
. Cependant, mt_getrandmax()
ne renvoie généralement que 2147483647
. Cela signifie que vous ne disposez que de 31 bits d'information, tandis qu'un double a une mantisse de 52 bits, ce qui signifie qu'il existe une densité d'au moins 2^53
pour les nombres compris entre 0 et 1.
Cette approche plus compliquée vous donnera une distribution plus fine:
function Rand_754_01() {
// Generate 64 random bits (8 bytes)
$entropy = openssl_random_pseudo_bytes(8);
// Create a string of 12 '0' bits and 52 '1' bits.
$x = 0x000FFFFFFFFFFFFF;
$first12 = pack("Q", $x);
// Set the first 12 bits to 0 in the random string.
$y = $entropy & $first12;
// Now set the first 12 bits to be 0[exponent], where exponent is randomly chosen between 1 and 1022.
// Here $e has a probability of 0.5 to be 1022, 0.25 to be 1021, etc.
$e = 1022;
while($e > 1) {
if(mt_Rand(0,1) == 0) {
break;
} else {
--$e;
}
}
// Pack the exponent properly (add four '0' bits behind it and 49 more in front)
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
// Now convert to a double.
return unpack("d", $y | $z)[1];
}
Veuillez noter que le code ci-dessus ne fonctionne que sur les ordinateurs 64 bits avec un ordre d'octets Litte-Endian et une représentation IEEE754 de type Intel. (x64
- les ordinateurs compatibles auront ceci). Malheureusement, PHP n'autorise pas le décalage de bits après les limites de taille int32
, vous devez donc écrire une fonction distincte pour Big-Endian.
Vous devriez remplacer cette ligne:
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
avec son homologue big-endian:
$z = pack("S", $e << 4) . "\0\0\0\0\0\0";
La différence n’est notable que lorsque la fonction est appelée un grand nombre de fois: 10^9
ou plus.
Vérifier si cela fonctionne
Il devrait être évident que la mantisse suit une approximation de distribution uniforme de Nice, mais il est moins évident que la somme d'une grande quantité de telles distributions (chacune avec une chance et une amplitude cumulées de moitié) est uniforme.
Fonctionnement:
function randomNumbers() {
$f = 0.0;
for($i = 0; $i < 1000000; ++$i) {
$f += \math::Rand_754_01();
}
echo $f / 1000000;
}
Produit une sortie de 0.49999928273099
(ou un nombre similaire proche de 0.5).
Solution for PHP 7. Génère un nombre aléatoire dans [0,1)
. c'est-à-dire comprend 0 et exclut 1.
function random_float() {
return random_int(0, PHP_INT_MAX-1)/PHP_INT_MAX;
}
J'ai trouvé la réponse sur PHP.net
<?php
function randomFloat($min = 0, $max = 1) {
return $min + mt_Rand() / mt_getrandmax() * ($max - $min);
}
var_dump(randomFloat());
var_dump(randomFloat(2, 20));
?>
float(0.91601131712832)
float(16.511210331931)
Alors tu pourrais faire
randomFloat(0,1);
ou simple
mt_Rand() / mt_getrandmax() * 1;