unico repetir rand numeros numero insertar generar ejemplo digitos datos con como codigo aleatorios aleatorio php random

repetir - ¿Generar resultados aleatorios por peso en PHP?



rand php ejemplo (12)

Acabo de lanzar una clase para realizar una clasificación ponderada fácilmente.

Se basa en el mismo algoritmo mencionado en Allain''s respuestas de Brad''s y Allain''s , y está optimizado para la velocidad, probado en unidades para una distribución uniforme y admite elementos de cualquier tipo de PHP.

Usarlo es simple. Crear una instancia:

$picker = new Brick/Random/RandomPicker();

A continuación, agregue elementos como una matriz de valores ponderados (solo si sus elementos son cadenas o enteros):

$picker->addElements([ ''foo'' => 25, ''bar'' => 50, ''baz'' => 100 ]);

O use llamadas individuales a addElement() . Este método admite cualquier tipo de valores de PHP como elementos (cadenas, números, objetos, ...), a diferencia del enfoque de matriz:

$picker->addElement($object1, $weight1); $picker->addElement($object2, $weight2);

Luego obtén un elemento aleatorio:

$element = $picker->getRandomElement();

La probabilidad de obtener uno de los elementos depende de su peso asociado. La única restricción es que los pesos deben ser enteros.

Sé cómo generar un número aleatorio en PHP, pero digamos que quiero un número aleatorio entre 1 y 10, pero quiero más 3,4,5 y luego 8,9,10. ¿Cómo es esto posible? Publicaría lo que intenté pero, sinceramente, ni siquiera sé por dónde empezar.


Basado en la answer / link @ Allain, desarrollé esta función rápida en PHP. Tendrá que modificarlo si desea usar un peso no entero.

/** * getRandomWeightedElement() * Utility function for getting random values with weighting. * Pass in an associative array, such as array(''A''=>5, ''B''=>45, ''C''=>50) * An array like this means that "A" has a 5% chance of being selected, "B" 45%, and "C" 50%. * The return value is the array key, A, B, or C in this case. Note that the values assigned * do not have to be percentages. The values are simply relative to each other. If one value * weight was 2, and the other weight of 1, the value with the weight of 2 has about a 66% * chance of being selected. Also note that weights should be integers. * * @param array $weightedValues */ function getRandomWeightedElement(array $weightedValues) { $rand = mt_rand(1, (int) array_sum($weightedValues)); foreach ($weightedValues as $key => $value) { $rand -= $value; if ($rand <= 0) { return $key; } } }


Como utilicé la solución de IainMH, también puedo compartir mi código PHP:

<pre><?php // Set total number of iterations $total = 1716; // Set array of random number $arr = array(1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5); $arr2 = array(0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 5); // Print out random numbers for ($i=0; $i<$total; $i++){ // Pick random array index $rand = array_rand($arr); $rand2 = array_rand($arr2); // Print array values print $arr[$rand] . "/t" . $arr2[$rand2] . "/r/n"; } ?></pre>


El truco ingenuo para esto sería construir una lista o una matriz como

1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10

Y luego selecciona al azar de eso.


Hay un link .

Básicamente:

  1. Suma los pesos de todos los números.
  2. Elija un número aleatorio menor que ese
  3. reste los pesos en orden hasta que el resultado sea negativo y devuelva ese número si lo es.

Llano y justo. Solo copie / pegue y pruébelo.

/** * Return weighted probability * @param (array) prob=>item * @return key */ function weightedRand($stream) { $pos = mt_rand(1,array_sum(array_keys($stream))); $em = 0; foreach ($stream as $k => $v) { $em += $k; if ($em >= $pos) return $v; } } $item[''30''] = ''I have more chances than everybody :]''; $item[''10''] = ''I have good chances''; $item[''1''] = ''I/'m difficult to appear...''; for ($i = 1; $i <= 10; $i++) { echo weightedRand($item).''<br />''; }

Editar: agregado soporte faltante al final.


Muchas de las respuestas en esta página parecen usar distensión de matriz, iteración excesiva, una biblioteca o un proceso difícil de leer. Por supuesto, todos piensan que su propio bebé es el más lindo, pero honestamente creo que mi enfoque es delgado, simple y fácil de leer / modificar ...

Según el OP, crearé una matriz de valores (declarados como claves) de 1 a 10, con 3, 4 y 5 con el doble del peso de los otros valores (declarados como valores).

$values_and_weights=array( 1=>1, 2=>1, 3=>2, 4=>2, 5=>2, 6=>1, 7=>1, 8=>1, 9=>1, 10=>1 );

Si solo vas a hacer una selección al azar y / o tu matriz es relativamente pequeña * (haz tu propio benchmarking para estar seguro), esta es probablemente tu mejor opción:

$pick=mt_rand(1,array_sum($values_and_weights)); $x=0; foreach($values_and_weights as $val=>$wgt){ if(($x+=$wgt)>=$pick){ echo "$val"; break; } }

Este enfoque no implica modificación de matriz y probablemente no será necesario iterar toda la matriz (pero sí).

Por otro lado, si va a hacer más de una selección al azar en la matriz y / o su matriz es suficientemente grande * (haga su propia evaluación comparativa para estar seguro), la reestructuración de la matriz puede ser mejor.

El costo en memoria para generar una nueva matriz se justificará cada vez más como:

  1. el tamaño de la matriz aumenta y
  2. número de selecciones aleatorias aumenta.

La nueva matriz requiere el reemplazo de "peso" por un "límite" para cada valor al sumar el peso del elemento anterior al peso del elemento actual.

A continuación, voltee la matriz de modo que los límites sean las teclas de la matriz y los valores sean los valores de la matriz. La lógica es: el valor seleccionado tendrá el límite más bajo que sea> = $ pick.

// Declare new array using array_walk one-liner: array_walk($values_and_weights,function($v,$k)use(&$limits_and_values,&$x){$limits_and_values[$x+=$v]=$k;}); //Alternative declaration method - 4-liner, foreach() loop: /*$x=0; foreach($values_and_weights as $val=>$wgt){ $limits_and_values[$x+=$wgt]=$val; }*/ var_export($limits_and_values);

Crea esta matriz:

array ( 1 => 1, 2 => 2, 4 => 3, 6 => 4, 8 => 5, 9 => 6, 10 => 7, 11 => 8, 12 => 9, 13 => 10, )

Ahora para generar el $pick aleatorio y seleccionar el valor:

// $x (from walk/loop) is the same as writing: end($limits_and_values); $x=key($limits_and_values); $pick=mt_rand(1,$x); // pull random integer between 1 and highest limit/key while(!isset($limits_and_values[$pick])){++$pick;} // smallest possible loop to find key echo $limits_and_values[$pick]; // this is your random (weighted) value

Este enfoque es brillante porque isset() es muy rápido y el número máximo de llamadas isset() en el ciclo while solo puede ser el mayor (no confundirse con el límite) de la matriz. Para este caso, iteraciones máximas = 2!

ESTE ENFOQUE NUNCA NECESITA PARA ITERAR TODO EL ARRAY


Para un número aleatorio eficiente sesgado consistentemente hacia un extremo de la escala:

  • Elija un número aleatorio continuo entre 0..1
  • Elevar a un poder γ, para sesgarlo. 1 es no ponderado, más bajo da más de los números más altos y viceversa
  • Escala al rango deseado y redondo a entero

p.ej. en PHP (no probado):

function weightedrand($min, $max, $gamma) { $offset= $max-$min+1; return floor($min+pow(lcg_value(), $gamma)*$offset); } echo(weightedrand(1, 10, 1.5));


Puede usar weightedChoice desde una biblioteca PHP no estándar . Acepta una lista de pares (elemento, peso) para tener la posibilidad de trabajar con elementos que no pueden ser claves de matriz. Puede usar la función de pairs para convertir la array(item => weight) al formato necesario.

use function /nspl/a/pairs; use function /nspl/rnd/weightedChoice; $weights = pairs(array( 1 => 10, 2 => 15, 3 => 15, 4 => 15, 5 => 15, 6 => 10, 7 => 5, 8 => 5, 9 => 5, 10 => 5 )); $number = weightedChoice($weights);

En este ejemplo, 2-5 aparecerá 3 veces más a menudo que 7-10.


function getBucketFromWeights ($ values) {$ total = $ currentTotal = $ bucket = 0;

foreach ($values as $amount) { $total += $amount; } $rand = mt_rand(0, $total-1); foreach ($values as $amount) { $currentTotal += $amount; if ($rand => $currentTotal) { $bucket++; } else { break; } } return $bucket;

}

Modifiqué esto de una respuesta aquí Escogiendo elementos aleatorios por pesos definidos por el usuario

Después de escribir esto, vi que alguien tenía una respuesta aún más elegante. Él él el.


Este tutorial lo guiará a través de él, en PHP, con múltiples soluciones de cortar y pegar. Tenga en cuenta que esta rutina se modifica ligeramente de lo que encontrará en esa página, como resultado del comentario a continuación.

Una función tomada de la publicación:

/** * weighted_random_simple() * Pick a random item based on weights. * * @param array $values Array of elements to choose from * @param array $weights An array of weights. Weight must be a positive number. * @return mixed Selected element. */ function weighted_random_simple($values, $weights){ $count = count($values); $i = 0; $n = 0; $num = mt_rand(1, array_sum($weights)); while($i < $count){ $n += $weights[$i]; if($n >= $num){ break; } $i++; } return $values[$i]; }


/** * @param array $weightedValues * @return string */ function getRandomWeightedElement(array $weightedValues) { $array = array(); foreach ($weightedValues as $key => $weight) { $array = array_merge(array_fill(0, $weight, $key), $array); } return $array[array_rand($array)]; }

getRandomWeightedElement(array(''A''=>10, ''B''=>90));

Este es un método muy fácil. Cómo obtener elemento ponderado al azar. Lleno la variable variable $ clave. Obtengo $ key para array $ weight x. Después de eso, usa array_rand to array. Y tengo un valor aleatorio;).