2011-09-02 11 views
5

sai un modo per dividere un intero in dire ... 5 gruppi. Ogni totale di gruppo deve essere casuale ma il totale deve essere uguale a un numero fisso.Come fare 5 numeri casuali con la somma di 100

per esempio ho "100" Voglio dividere questo numero nella

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

EDIT: Ho dimenticato di dire che sì un equilibrio sarebbe una buona thing.I Suppongo che questo potrebbe essere fatto facendo un caso dichiarazione che blocca qualsiasi numero superiore a 30 istanze.

+1

questo è possibile. Hai fatto qualche tentativo? –

+1

Con quale parte di questo hai problemi? Sai come generare numeri casuali? –

+0

Questo non sembra un problema su PHP? – benck

risposta

4

A seconda di come casuale avete bisogno di essere e come ricca risorsa è l'ambiente si prevede di eseguire lo script, si potrebbe provare il seguente approccio.

<?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; 
    } 
} 

L'esempio del risultato generato sarà simile a questo. Abbastanza casuale.

[[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

ciao, puoi spiegare perché all'interno della condizione if hai messo $ group = 0? Non riesco a capire l'utilizzo –

+0

Penso di averlo capito. È fatto per trovare un numero finale per raggiungere il totale, giusto? Molto intelligente :) –

0

penso che il trucco per questo è quello di mantenere fissa il massimale per il vostro # generatore casuale di 100 - currentTotal

+0

Questo approccio non ti darà una distribuzione particolarmente equilibrata (i primi elementi sono probabilmente molto più grandi degli elementi successivi, in media). Ma per essere onesti, l'OP non ha specificato la distribuzione. –

1

Questo dovrebbe fare quello che ti serve:

<?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; 

Non si darà un distribuzione veramente equilibrata, tuttavia, poiché i primi numeri saranno in media più grandi.

+0

Ho ottenuto 'Array ([0] => 11 [1] => 48 [2] => 26 [3] => 7 [4] => 6)'. Ciò equivale a 98. – webbiedave

+0

Whoops, risolto. L'ultimo numero non è casuale, però. – EdoDodo

+1

Se si desidera "bilanciare la distribuzione", è possibile aggiungere un passaggio alla fine per rendere casuale l'indice dell'array. – horatio

5

Scegliere 4 numeri casuali, ciascuno attorno a una media di 20 (con distribuzione di circa il 40% di 20, cioè 8). Aggiungi un quinto numero in modo che il totale sia 100.

In risposta a molte altre risposte qui, in effetti l'ultimo numero non può essere casuale, perché la somma è fissa. Come spiegazione, nell'immagine sottostante, ci sono solo 4 punti (tick più piccoli) che possono essere scelti casualmente, rappresentati cumulativamente con ciascuno aggiungendo un numero casuale attorno alla media di tutti (totale/n, 20) per avere una somma di 100. Il risultato sono 5 spaziature, che rappresentano i 5 numeri casuali che stai cercando.

only 4 random point between 0 and 100

+0

@Sandro Antonucci: ho appena adattato la mia spiegazione e ho visto che il tuo esempio 20,3,34,15,18 non aggiunge 100. Ma questo è ciò che intendi, giusto? (ottenuto un downvote sulla mia risposta precedente e mi sono chiesto perché) – 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

sembra ok, il problema è che se un numero è alto ridurrà matematicamente i "gruppi" totali che raggiungono il totale prima. Come si può dire allo script di "continuare a provare" un numero casuale fino a quando non è inferiore a 30, ad esempio? –

+0

'if ($ sub_number <= 30) { \t \t $ iterazione ++; \t \t numero $ - = $ sub_number; \t \t $ numeri [] = $ sub_number; \t} aggiungendo questo funziona, ma l'ultimo numero potrebbe diventare enorme –

+0

Si esploderà se il primo numero è 95 o superiore. 95,1,2,?,?,? se non è consentita alcuna ripetizione o 99,1,?,?,? se sono. –

0

La soluzione che ho trovato a questo problema è un po 'diverso, ma rende più senso per me, quindi in questo esempio ho generare una serie di numeri che aggiungono fino a 960. Spero che questo è utile.

// 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 soluzione dipende da come casuale si desidera che il valore di essere, in altre parole, quale situazione casuale che si vuole simulare.

Per ottenere la distribuzione del tutto casuale, dovrete fare 100 sondaggi in cui ogni elemento sarà rilegato ad un gruppo, in un linguaggio simbolico

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

Per i numeri più grandi, si potrebbe aumentare il gruppo selezionato da random(1, n/100) o qualcosa del genere fino a quando la somma totale corrisponderebbe al n.

Tuttavia, si desidera ottenere il saldo, quindi penso che il migliore per voi sarebbe la distribuzione normale. Disegna 5 valori gaussiani, che divideranno il numero (la loro somma) in 5 parti. Ora devi ridimensionare queste parti in modo che la loro somma sia n e intorno a loro, così hai ottenuto i tuoi 5 gruppi.

4

Ho un approccio leggermente diverso ad alcune delle risposte qui. Creo una percentuale libera in base al numero di elementi che si desidera sommare e quindi più o meno il 10% su base casuale.

Quindi faccio questo n-1 volte (n è totale di iterazioni), quindi hai un resto. Il resto è quindi l'ultimo numero, che non è di per sé casuale, ma si basa su altri numeri casuali.

Funziona piuttosto bene.

/** 
* 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; 
} 

questo:

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

Uscite:

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