2015-12-17 29 views
5

La generazione di un numero casuale nell'intervallo [M..N] è abbastanza semplice. Vorrei tuttavia generare una serie di numeri casuali in tale intervallo con la media X (M < X < N).Genera un numero casuale nell'intervallo [M .... N] con media X

Ad esempio, assumere la seguente: M = 10000 N = 1000000 X = 20000 desidero generare (una grande quantità di) numeri casuali tale che l'intero intervallo [M..N] è coperto , ma in questo caso i numeri più vicini a N dovrebbero diventare estremamente più rari. I numeri più vicini a M dovrebbero essere più comuni per garantire che la media converga a X.

Il linguaggio di destinazione previsto è PHP, ma questa non è una domanda di lingua di per sé.

+0

Hai un'idea di come dovrebbe essere la distribuzione? Puoi facilmente ottenerlo usando due distribuzioni uniformi (cioè una funzione casuale standard), una per [M..X] e una per [X..N] ponderate in modo che la media sia X. – Zong

+0

Interessante. Quindi una distribuzione uniforme in [M..X] avrebbe una media di (M + X)/2 e una distribuzione uniforme in [X..N] avrebbe una media di (X + N)/2 giusto? E poi appesantire quei due mezzi tali che il loro EV è X ... è questo che intendi? –

+0

Sì, dovresti semplicemente iniziare girando una moneta ponderata per decidere quale distribuzione usare. Questo soddisfa le tue esigenze ma potrebbe non dare la "forma" che desideri. – Zong

risposta

1

Ci sono molti modi per farlo, e sarebbe molto diverso a seconda delle esigenze di precisione. Il seguente codice utilizza lo 68-95-99.7 rule, basato sulla distribuzione normale, con una deviazione standard del 15% della media.

Non è così:

  • garantire precisione esatta. Se hai bisogno di questo devi calcolare la media reale e compensare l'importo mancante.
  • creava una curva distribuita normale in modo dinamico, poiché tutti e tre i blocchi (68-95-99.7) sono considerati uguali all'interno dei rispettivi gruppi.

Essa, tuttavia, vi darà un inizio:

<?php 

$mean = (int)$_GET['mean']; // The mean you want 
$amnt = (int)$_GET['amnt']; // The amount of integers to generate 
$sd = $mean * 0.15; 
$numbers = array(); 
for($i=1;$i<$amnt;$i++) 
{ 
    $n = mt_rand(($mean-$sd), ($mean+$sd)); 
    $r = mt_rand(10,1000)/10; // For decimal counting 
    if($r>68) 
    { 
     if(2==mt_rand(1,2)) // Coin flip, should it add or subtract? 
     { 
      $n = $n+$sd; 
     } 
     else 
     { 
      $n = $n-$sd; 
     } 
    } 
    if($r>95) 
    { 
     if(2==mt_rand(1,2)) 
     { 
      $n = $n+$sd; 
     } 
     else 
     { 
      $n = $n-$sd; 
     } 
    } 
    if($r>99.7) 
    { 
     if(2==mt_rand(1,2)) 
     { 
      $n = $n+$sd; 
     } 
     else 
     { 
      $n = $n-$sd; 
     } 
    } 
    $numbers[] = $n; 
} 

arsort($numbers); 
print_r($numbers); 

// Echo real mean to see how far off you get. Typically within 1% 

/* 
$sum = 0; 

foreach($numbers as $val) 
{ 
    $sum = $sum + $val; 
} 

echo $rmean = $sum/$amnt; 
*/ 

?> 

Speranza che aiuta!