2013-06-02 13 views
7

Sto pensando se c'è comunque un insieme di numeri casuali di cui la somma è sempre una costante. Ad esempio, 20 può essere diviso in 5 numeri (1, 2,3,4,10) Non mi interessa quale sia il numero di ognuno dei 5 numeri fino a che la loro somma è uguale a 20. C'è comunque da fare a livello di programmazione ?genera numeri casuali di cui la somma è costante

+0

Con "somma" , intendi "prodotto"? Anche se lo chiarisci, la domanda è ancora molto poco chiara. –

+0

http://stackoverflow.com/questions/8064629/random-numbers-that-add-to-100-matlab/8068956#8068956 –

+0

i numeri positivi solo o entrambi i numeri negativi possono essere lì? –

risposta

-1

Utilizzare una funzione di libreria per ottenere i numeri casuali.

Ora il numero casuale che si desidera è il numero casuale generato mod la somma consentita.

Quindi si decrementa la somma consentita per il numero appena generato.

Diciamo che il primo numero casuale vostro generatore di numeri casuali biblioteca torna è 109.

Così il vostro primo numero casuale è 109 mod 20 = 9. Aggiornare il vostro totale consentito di 20 -9 = 11.

Continui finché la somma consentita è zero.

Nota che presumo che il numero 5 che hai citato sia solo un esempio. Se si desidera che il numero di numeri casuali sia esattamente 5, potrebbe essere necessario modificare questo metodo.

+1

Non sarà uniforme. Questo creerà troppe distribuzioni che sono un grande numero e 4 piccoli. –

+0

DEFINITAMENTE non sarà uniforme. –

+0

Hai ragione - non sarà uniforme. Non pensavo che sarebbe stato necessario in questo caso particolare, specialmente seguendo il suo esempio. Nel caso generale, avremmo ovviamente bisogno di una distribuzione uniforme. – hojusaram

-1

sì! provare questo algoritmo

num1=rand()%20; 
num2=rand()%(20-num1); 
num3=rand()%(20-num1-num2); 
num4=rand()%(20-num1-num2-num3); 
num5=20-num4-num3-num2-num1; 

così per che i cinque numeri sono casuali e che riassumono al 20
[si può fare questo usando ciclo se si vuole]

In generale si può prima generare casualmente il numero di numeri [n] che riassumere il numero in mano [K]

n=rand()%k;--assuming the number of rand numbers you want are between 1 and k[sum] 
    n1=rand()%k; 
    n2=rand()%(k-n1) 
    . 
    . 
    nn-1=rand()%(k-n1...-nn-2) 
    nn=k-n1-n2...nn-1 

spero che vi aiuterà!

+0

Cosa succede se 'n1' è 19? – Kevin

+0

quindi c'è una probabilità che uno dei restanti 4 numeri sarà uno altrimenti saranno tutti zero. Se si desidera una distribuzione equa è necessario modificare l'algoritmo. come usare rand() mod 6 invece di rand() mod 20 – dsharew

+0

Ancora, questo non sarà un insieme uniforme. –

15

Per ottenere una distribuzione uniforme, il trucco è pensare la somma come una linea numerica e piuttosto che generare numeri casuali per i segmenti, generare numeri n-1 come punti lungo la linea e sottrarre per ottenere i segmenti . Ecco la funzione da ojrandlib:

static int compare(const void *a, const void *b) { 
    return *(int*)a - *(int*)b; 
} 
void ojr_array_with_sum(ojr_generator *g, int *a, int count, int sum) { 
    int i; 
    for (i = 0; i < count-1; ++i) { a[i] = ojr_rand(g, sum+1); } 
    qsort(a, count-1, sizeof(int), compare); 
    a[count-1] = sum; 
    for (i = count-1; i > 0; --i) { a[i] -= a[i-1]; } 
} 

ojr_rand(g, limit) genera un numero intero casuale uniforme da 0 a limitare-1. Questa funzione riempie quindi l'array a con numeri interi count casuali che si aggiungono a sum. Non dovrebbe essere troppo difficile adattarlo a qualsiasi altro RNG.

+0

+1. Penso che questo sia uniforme nelle dimensioni superiori, ma dovrei provarlo. Tuttavia, nessuna delle altre risposte è ancora vicina all'uniforme. Si noti che il problema più generale è un campionamento casuale di N numeri che giacciono tutti nell'intervallo [a, b] con una somma di X. E, naturalmente, generare numeri interi casuali che sommano a un dato numero è anche un problema interessante e correlato . –

+1

Davvero è una bellissima soluzione. Prendendo il problema e trasformandolo in qualcosa di diverso e più semplice che è equivalente e facilmente risolvibile - geniale. – SimpleVar

0

questo è un po 'un trucco, ma ancora :)
vi presento questa come una possibile idea, non dicendo che è il miglior
(e per lo più, avrete bisogno di numeri interi in modo che non funzionerà comunque)

interi Se i numeri casuali necessari non sono richieste:
allora è possibile generare numeri casuali tra N [0,1] e quindi normalizzare la matrice al S :)

for(i=0; i<N; i++) 
    arr[i] = rand; 

cursum = 0; 
for(i=0; i<N; i++) 
    cursum+=arr[i]; 

norm = S/cursum; 

for(i=0; i<N; i++) 
    arr[i] *= norm; 
0

Se i numeri generati non sono necesserily Posi tive o whitin un intervallo.
è possibile calcolare l'ultimo numero può essere S - SUM (A1..A [N-1])

selezione di N-1 numeri casuali è ovviamente uniforme,
e perché l'ultimo numero è comunque dipende dal resto dei numeri
(ogni serie ha solo un'opzione per l'ultimo numero).

l'uniformità non è ostacolata.

Arr = new int[N]; 

int sum=0; 
for(i=0; i<N-1; i++) 
{ 
    int x = getRandomInt(); 
    sum += x; 
    Arr[i] = x; 
} 
Arr[N-1] = S - sum; 
return Arr; 
0

Nel mio caso ho dovuto fare questo per matrice di valori, che prende Somma e si divide in serie di numeri a caso.

<html> 
<script type="text/javascript"> 
function f(){ 
var array = [{ 
    order: '1-2480831', 
    value: 2040 
}, { 
    order: 'BAESYS-2012-0001', 
    value: 570 
}, { 
    order: 'BAESYS-2012-0002', 
    value: 773 
}, { 
    order: '1-3840231', 
    value: 299 
}, { 
    order: '1-3840298', 
    value: 1609 
}, { 
    order: '1-3841519', 
    value: 1940 
}]; 

    var splitInto = 3; 

    document.write("["); 
    for (i=0; i<array.length; i++) 
    { 
     document.write("{ Id : '"+array[i].order+"', Data : ["); 
    var result = RandGenerator(splitInto,array[i].value); 
    var sum = 0; 
      for(ii =0;ii<result.length; ii++){ 
       sum += result[ii]; 
      document.write(result[ii]+','); 
      } 
      document.write("]},"); 
    } 
    document.write("]"); 
} 

function RandGenerator(count, sum) { 
    var a = []; 
    for (iii = 0; iii < count-1; iii++) 
     { 
      a[iii] = getRandToValue(sum); 
      sum -= a[iii]; 
     } 
    a[count-1] = sum; 
    return a; 
} 

function getRandToValue(maxRand) 
{ 
    var random = Math.random(); 
    var computed = (maxRand)*random; 
    return computed; 
} 

f(); 
</script> 
</html> 
1

Questo metodo fa il lavoro, e permette anche di controllare il "grado differenza" tra i valori (ad esempio, se si desidera che i valori di matrice di essere vicino l'un l'altro)

/** 
    * Create array of positive integers which exactly sums to a given (integer) number. 
    * @param {Number} number of items 
    * @param {Number} sum required sum 
    * @param {Number} [d=100] difference degree between the values (0..100) 
    */ 
    randomSumArray: function(len, sum, d) { 
     var _sum = 0; 
     var arr = []; 
     var n, i; 

     if (!d && d !== 0) { 
      d = 100; 
     } 

     for (i = 0; i < len; i++) { 
      var from = (100 - d) * 1000, 
       to = (100 + d) * 1000, 
       n = Math.floor(Math.random() * (to - from + 1) + from); //random integer between from..to 

      _sum += n; 
      arr.push(n); 
     } 

     var x = sum/_sum; 

     _sum = 0; //count sum (again) 
     for (var i = 0; i < len; i++) { 
      arr[i] = Math.round(arr[i] * x); 
      _sum += arr[i]; 
     } 

     var diff = sum - _sum; 

     // Correct the array if its sum does not match required sum (usually by a small bit) 
     if (diff) { 
      x = diff/Math.abs(diff); //x will be 1 or -1 
      var j = 0; 
      while (diff && j < 1000) { //limit to a finite number of 'corrections' 
       i = Math.floor(Math.random() * (len + 1)); //random index in the array 
       if (arr[i] + x >= 0) { 
        arr[i] += x; 
        diff -= x; 
       } 
       j++; 
      } 
     } 

     return arr; 
    } 
Problemi correlati