Generazione di numeri pseudocasuali
Rand
La funzione Matlab rand() genera numeri pseudocasuali compresi tra 0 e 1. Per generare un numero pseudocasuale è sufficiente scrivere:
>> rand(1)
ans =
0.8147
la distribuzione dei valori tra 0 e 1 è lineare e ad ogni chiamata viene restituito un numero diverso.
Il problema delle sequenze pseudocasuali è che ad ogni riavvio di Matlab viene restituita la stessa sequenza di numeri, ovvero se si chiude e riapre Matlab e si riscrive rand(1) come primo valore viene restituito sempre 0.8147.
Il problema deriva dal fatto che le sequenze di numeri psudocasuali vengono generate sempre a partire da un numero chiamato "seed" (seme) e questo, a meno non venga cambiato, è sempre lo stesso. Ovviamente, i calcoli che utilizzano gli stessi numeri "casuali" non possono essere considerati statisticamente indipendenti. Pertanto, quando è necessario combinare i calcoli eseguiti in due o più sessioni MATLAB come se fossero statisticamente indipendenti, non è possibile utilizzare le impostazioni predefinite del generatore.
Per evitare la ripetizione della stessa sequenza ad ogni accensione, l'help di Matlab suggerisce di reinizializzare il generatore di numeri casuali usando il comando rng:
>> rng shuffle
>> rand(1)
Ogni volta che viene usato, "shuffle" esegue il reseeding del generatore con un seme diverso.
È possibile chiamare rng senza input per vedere quale seme viene effettivamente utilizzato:
>> rng
ans =
struct with fields:
Type: 'twister'
Seed: 0
State: [625×1 uint32]
ATTENZIONE: "shuffle" è un modo molto semplice per modificare il generatore di numeri casuali. Si potrebbe pensare che sia una buona idea, o addirittura necessario, usarlo per ottenere una "vera" casualità. Per la maggior parte degli scopi, tuttavia, non è affatto necessario utilizzare "shuffle". La scelta di un seme basato sull'ora corrente non migliora le proprietà statistiche dei valori ottenuti da rand e non li rende "più casuali". Sebbene sia perfettamente corretto eseguire il reseeding del generatore ogni volta che si avvia Matlab o prima di eseguire un calcolo di grandi dimensioni che coinvolge numeri casuali, non è invece corretto eseguire il reseeding del generatore troppo frequentemente all'interno della stessa sessione (o m-file), poiché ciò può influire le proprietà statistiche dei numeri casuali generati.
rand() è in grado di generare anche vettori e matrici di numeri psudocasuali:
>> rand(5,1)
ans =
0.2769
0.0462
0.0971
0.8235
0.6948
>> rand(2,3)
ans =
0.3171 0.0344 0.3816
0.9502 0.4387 0.7655
RandN
randn() genera una sequenza di numeri pseudocasuali con distribuzione gaussiana normale, ovvero i numeri generati si trovano attorno allo zero, ma la probabilità che un numero sia estratto è distribuita secondo il grafico in figura
Si osserva che tutti i numeri sono generabili, per esempio 100000 è un numero che può uscire, tuttavia la probabilità che esca un numero compreso tra -3 e 3 è del 99.73%.
Questa distribuzione è significativa perché, per esempio, gli errori di misura hanno questo tipo di distribuzione.
randn() ha lo stesso funzionamento di rand() e ha quindi gli stessi problemi relativamente al seed.
>> randn(1)
ans =
0.3129
>> randn(4,2)
ans =
0.3129 0.6277
-0.8649 1.0933
-0.0301 1.1093
-0.1649 -0.8637
Randi
randi( n ) genera una sequenza pseudocasuale di interi compresi tra 1 e n.
randi(6) va quindi molto bene per simulare il lancio di un dado e randi(2) per il lancio di una moneta:
>> d = randi(6); >> disp(['Valore dado: ',num2str(d)]);
Valore dado: 3
Anche la distribuzione di randi( n ) è lineare, ovvero il dado non è truccato.
Anche questa sequenza è pseudocasuale e soffre del problema di seed al riavvio di Matlab già visto in precedenza.
Randperm
randperm() è anch'esso un generatore di numeri interi pseudocasuali.
randperm( n ) restituisce un vettore riga contenente una permutazione casuale degli interi da 1 a n senza elementi ripetuti. Per esempio randperm(90) restituisce il risultato completo di un'estrazione senza reinserimento di 90 numeri, ovvero un'estrazione completa del gioco della tombola.
>> randperm(90)
ans =
Columns 1 through 11
67 43 36 35 90 63 56 71 65 40 80
Columns 12 through 22
12 84 79 13 59 45 49 77 21 4 57
Columns 23 through 33
18 22 16 6 14 73 51 78 30 47 44
Columns 34 through 44
2 20 87 25 33 72 89 75 64 55 42
Columns 45 through 55
24 7 88 48 37 61 11 28 83 34 41
Columns 56 through 66
82 27 3 50 23 86 52 53 8 54 5
Columns 67 through 77
32 31 68 38 46 74 17 69 60 26 15
Columns 78 through 88
85 70 81 9 76 58 29 19 39 10 1
Columns 89 through 90
66 62
randperm( n, k ) restituisce un vettore riga contenente k numeri interi senza ripetizione selezionati casualmente da 1 a n. Per esempio randperm(90,5) restituisce un'estrazione del lotto su una ruota.
>> v = randperm(90,5);
>> str = ['Estrazione ruota di venezia: ', num2str(v)];
>> disp(str);
Estrazione ruota di Venezia: 22 11 17 21 36
Anche questa sequenza è pseudocasuale e soffre del problema di seed al riavvio di Matlab.