2011-09-02 10 views
5

¿conoces una manera de dividir un número entero en decir ... 5 grupos. Cada total de grupo debe ser aleatorio, pero el total de ellos debe ser igual a un número fijo.Cómo hacer 5 números al azar con la suma de 100

por ejemplo tengo "100" yo quiero dividir este número en

1- 20 
2- 3 
3- 34 
4- 15 
5- 18 

EDIT: se me olvidó decir que si un equilibrio sería una buena thing.I suponen esto podría hacerse mediante una si declaración bloqueando cualquier número por encima de 30 instancia.

+1

esto es posible. ¿Has hecho algún intento? –

+1

¿Con qué parte de esto estás teniendo problemas? ¿Sabes cómo generar números aleatorios? –

+0

¿Esto no parece un problema con PHP? – benck

Respuesta

4

Dependiendo de qué tan al azar que lo necesite ser y cómo es rico en recursos del entorno en el que va a ejecutar la secuencia de comandos, puede probar con el siguiente enfoque.

<?php 
set_time_limit(10); 

$number_of_groups = 5; 
$sum_to    = 100; 

$groups    = array(); 
$group    = 0; 

while(array_sum($groups) != $sum_to) 
{ 
    $groups[$group] = mt_rand(0, $sum_to/mt_rand(1,5)); 

    if(++$group == $number_of_groups) 
    { 
     $group = 0; 
    } 
} 

El ejemplo del resultado generado se verá más o menos así. Bastante al azar.

[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(11) 
    [1]=> 
    int(2) 
    [2]=> 
    int(13) 
    [3]=> 
    int(9) 
    [4]=> 
    int(65) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(9) 
    [1]=> 
    int(29) 
    [2]=> 
    int(21) 
    [3]=> 
    int(27) 
    [4]=> 
    int(14) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(18) 
    [1]=> 
    int(26) 
    [2]=> 
    int(2) 
    [3]=> 
    int(5) 
    [4]=> 
    int(49) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(20) 
    [1]=> 
    int(25) 
    [2]=> 
    int(27) 
    [3]=> 
    int(26) 
    [4]=> 
    int(2) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(9) 
    [1]=> 
    int(18) 
    [2]=> 
    int(56) 
    [3]=> 
    int(12) 
    [4]=> 
    int(5) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(0) 
    [1]=> 
    int(50) 
    [2]=> 
    int(25) 
    [3]=> 
    int(17) 
    [4]=> 
    int(8) 
} 
[[email protected] ~]# php /var/www/dev/test.php 
array(5) { 
    [0]=> 
    int(17) 
    [1]=> 
    int(43) 
    [2]=> 
    int(20) 
    [3]=> 
    int(3) 
    [4]=> 
    int(17) 
} 
+0

hola, ¿puede explicar por qué dentro de la condición if pone $ group = 0? No puedo entender el uso –

+0

Creo que lo tengo. Está hecho para encontrar un número final para alcanzar el total, ¿verdad? Muy inteligente :) –

0

creo que el truco para esto es mantener establecer un límite para su generador aleatorio # 100 - currentTotal

+0

Este enfoque no le dará una distribución particularmente equilibrada (los primeros elementos son, en promedio, mucho mayores que los elementos posteriores). Pero para ser justos, el OP no especificó la distribución. –

1

Esto debería hacer lo que tiene:

<?php 
$tot = 100; 
$groups = 5; 
$numbers = array(); 
for($i = 1; $i < $groups; $i++) { 
    $num = rand(1, $tot-($groups-$i)); 
    $tot -= $num; 
    $numbers[] = $num; 
} 
$numbers[] = $tot; 

No te va a dar una distribución verdaderamente equilibrada, ya que los primeros números serán, en promedio, más grandes.

+0

Tengo 'Matriz ([0] => 11 [1] => 48 [2] => 26 [3] => 7 [4] => 6)'. Eso suma 98. – webbiedave

+0

Whoops, corregido. Sin embargo, el último número no es aleatorio. – EdoDodo

+1

Si desea "equilibrar la distribución", puede agregar un paso al final para aleatorizar el índice de la matriz. – horatio

5

Elija 4 números aleatorios, cada uno alrededor de un promedio de 20 (con una distribución de, por ejemplo, alrededor del 40% de 20, es decir, 8). Agregue un quinto número tal que el total sea 100.

En respuesta a varias otras respuestas aquí, de hecho, el último número no puede ser aleatorio, porque la suma es fija. Como explicación, en la imagen de abajo, solo hay 4 puntos (marcas más pequeñas) que pueden elegirse al azar, representadas de forma acumulativa y cada una sumando un número aleatorio alrededor de la media de todas (total/n, 20) para tener una suma de 100. El resultado es 5 espacios, que representan los 5 números aleatorios que está buscando.

only 4 random point between 0 and 100

+0

@Sandro Antonucci: acabo de adaptar mi explicación y vi que su ejemplo 20,3,34,15,18 no suma 100. Pero esto es lo que quiere decir, ¿no? (obtuve un voto negativo sobre mi respuesta anterior y me pregunté por qué) – Remi

3
$number = 100; 
$numbers = array(); 
$iteration = 0; 
while($number > 0 && $iteration < 5) { 
    $sub_number = rand(1,$number); 
    if (in_array($sub_number, $numbers)) { 
     continue; 
    } 
    $iteration++; 
    $number -= $sub_number; 
    $numbers[] = $sub_number;  
} 

if ($number != 0) { 
    $numbers[] = $number; 
} 

print_r($numbers); 
+0

esto se ve bien, el problema es que si un número es alto, reducirá matemáticamente el total de "grupos" que alcanzan el total antes. ¿Cómo puede decirle a la secuencia de comandos que "siga intentando" un número aleatorio hasta que sea inferior a 30, por ejemplo? –

+0

'if ($ sub_number <= 30) { \t \t $ iteration ++; \t \t $ number - = $ sub_number; \t \t $ numbers [] = $ sub_number; \t} ' añadiendo esto funciona pero el último número podría volverse enorme –

+0

Estará explotado si su primer número es 95 o más. 95,1,2,?,?,? si no se permiten repeticiones, o 99,1,?,?,? si ellos estan. –

0

La solución que encontré a este problema es un poco diferente, pero hace más sentido para mí, por lo que en este ejemplo genero una serie de números que suman hasta 960. Espero que esto es útil.

// the range of the array 
$arry = range(1, 999, 1); 
// howmany numbers do you want 
$nrresult = 3; 
do { 
    //select three numbers from the array 
    $arry_rand = array_rand ($arry, $nrresult); 
    $arry_fin = array_sum($arry_rand); 
    // dont stop till they sum 960 
} while ($arry_fin != 960); 

//to see the results 
foreach ($arry_rand as $aryid) { 
    echo $arryid . '+ '; 
} 
0

La solución depende de cómo al azar que quiere que sus valores sean, en otras palabras, qué situación aleatoria que vas a simular.

Para obtener la distribución totalmente aleatoria, que tendrá que hacer 100 encuestas en la que cada elemento se enganchan a un grupo, en un lenguaje simbólico

foreach i from 1 to n 
    group[ random(1,n) ] ++; 

Para los números más grandes, se puede aumentar el grupo seleccionado por random(1, n/100) o algo así hasta que la suma total corresponda a la n.

Sin embargo, desea obtener el saldo, por lo que creo que lo mejor para usted sería la distribución normal. Dibuje 5 valores gaussianos, que dividirán el número (su suma) en 5 partes. Ahora necesita escalar estas partes para que su suma sea ny redonda, por lo que tiene sus 5 grupos.

4

Tengo un enfoque ligeramente diferente a algunas de las respuestas aquí. Creé un porcentaje flexible basado en la cantidad de elementos que desea sumar, y luego más o menos 10% de forma aleatoria.

Entonces hago esto n-1 veces (n es el total de iteraciones), por lo que tiene un resto. El resto es el último número, que no es en sí mismo aleatorio, pero está basado en otros números aleatorios.

Funciona bastante bien.

/** 
* Calculate n random numbers that sum y. 
* Function calculates a percentage based on the number 
* required, gives a random number around that number, then 
* deducts the rest from the total for the final number. 
* Final number cannot be truely random, as it's a fixed total, 
* but it will appear random, as it's based on other random 
* values. 
* 
* @author Mike Griffiths 
* @return Array 
*/ 
private function _random_numbers_sum($num_numbers=3, $total=500) 
{ 
    $numbers = []; 

    $loose_pcc = $total/$num_numbers; 

    for($i = 1; $i < $num_numbers; $i++) { 
     // Random number +/- 10% 
     $ten_pcc = $loose_pcc * 0.1; 
     $rand_num = mt_rand(($loose_pcc - $ten_pcc), ($loose_pcc + $ten_pcc)); 

     $numbers[] = $rand_num; 
    } 

    // $numbers now contains 1 less number than it should do, sum 
    // all the numbers and use the difference as final number. 
    $numbers_total = array_sum($numbers); 

    $numbers[] = $total - $numbers_total; 

    return $numbers; 
} 

Este:

$random = $this->_random_numbers_sum(); 
echo 'Total: '. array_sum($random) ."\n"; 
print_r($random); 

Salidas:

Total: 500 
Array 
(
    [0] => 167 
    [1] => 164 
    [2] => 169 
) 
Cuestiones relacionadas