I numeri casuali

Ultima modifica: 30-05-2016

Lavorando con fogli elettronici e con i numeri, prima o poi ci imbattiamo nella necessità di avere a disposizione alcuni eventi casuali.

Questa possibilità i viene concessa molto generosamente sia da Excel che dal VBA. Se poi non sappiamo proprio come cominciare Excel ci offre anche uno strumento molto utile che è il registratore di macro.

Una Macro è costituita da una serie di istruzioni e funzioni collocate in moduli di VBA e può essere richiamata ogni volta riteniamo la necessità.di eseguire una determinata operazione.

Anche per costruire un programma a volte può tornare utile il registratore di macro per trovare magari già pronte alcune istruzioni un pò complesse.

Una volta registrata la macro, sarà possibile visualizzarne il codice nell'editor del VBA per correggere eventuali imprecisioni o modificare l'azione eseguita dalla macro. Se ad esempio si desidera che la macro colori una determinata cella e poi applichi anche il grassetto al testo in essa contenuta, sarà possibile registrare prima una macro che dia il colore desiderato alla cella e poi un'altra macro per formattare la cella in grassetto, quindi copiare le istruzioni da quest'ultima nella prima.

Perciò, per compiere queste semplici operazioni non occorre imparare a programmare o a utilizzare il linguaggio di Visual Basic. Una volta in possesso di adeguate istruzioni è facile copiarle, spostarle tra un modulo ed un altro, modificarle come più ci aggrada e molto ancora.

Vediamo quindi qualche semplice funzione che possiamo evocare direttamente dal foglio di Excel assieme al registratore di macro e poi modificare come meglio riteniamo opportuno.

Questa che vado a presentare è una macro che contiene due funzioni:

Int e Rnd()

Sub Macro5()
'
' Macro5 Macro
' Macro registrata il 11/05/2003 da MM
'
'
ActiveCell.FormulaR1C1 = "=INT(RAND()*70+1)"
End Sub

Dopo una adeguata limatura della macro ci ritroviamo con:

Sub Macro5()
ActiveCell.FormulaR1C1 = "=INT(RAND()*70+1)"
End Sub

Ma cosa fanno queste due funzioni?

Per la maggior parte dei comuni mortali la funzione Int(argomento) non ha bisogno di commenti: c'è solo da ricordare che restituisce la parte intera di un numero.

Di una particolare attenzione ha invece bisogno la funzione RAND() registrata col registratore di macro oppure Rnd() se scritta direttamente nell'editor VBA.

In questa sede, tanto per semplificarci la vita, ci basta sapere che questa funzione restituisce un numero casuale compreso tra 0 (zero - compreso) ed 1 (escluso), quindi un numero decimale casuale.

Nella maggior parte dei casi, tuttavia, a noi non occorre un numero di questo tipo, ma un numero casuale compreso in un certo intervallo (per esempio, un numero compreso tra 1 e 90, o un numero tra 120 e 1200). Per appagare questa aspettativa dobbiamo fare e, di conseguenza far fare al codice, questo ragionamento:

prendiamo la parte intera di Int
un numero casuale RAND() o Rnd()
lo moltiplichiamo per 90 (che è il numero massimo che noi ci aspettiamo in questo caso) *90
e lo aumentiamo di una unità (non dimentichiamo che la funzione potrebbe anche restituirci un bello 0 che non ci serve e non mai un 1) +1

E se ci serve un numero compreso tra un valore minimo ed uno massimo?

Molto semplicemente ci si presenta la formula ricavata dalla registrazione di una macro di Excel:

Sub Macro7()
ActiveCell.FormulaR1C1 = "=CASUALE.TRA(20,80)"
End Sub

A volte occorre tuttavia far ricorso alla funzione nativa del VBA per una maggiore flessibilità della stessa formula con la seguente sintassi dove è ammesso anche l'uso delle variabili:

Sub Macro8()
Valmin = 20
Valmax = 80
ActiveCell = Int(Rnd() * (Valmax - Valmin + 1)) + Valmin
End Sub

Come spiegato più sopra con la prima parte della formula: Int(Rnd() * (Valmax - Valmin + 1) otteniamo un numero compreso tra 1 e 60 in quanto con (Valmax - Valmin) otterremo 60 che poi innalziamo ad un intervallo compreso tra 20 ed 80 completando la formula con la seconda parte: + Valmin).

Vediamo subito con alcuni esempi alcune possibili applicazioni di questa funzione:

Sub Generatore_di_Numeri_Casuali()
Dim Valmax
Dim CL As Object
Dim MioIntervallo As Range
Set MioIntervallo = Range("A3:E20")
Valmax = 120
For Each CL In MioIntervallo
CL.Value = Int(Rnd() * Valmax + 1)
Next
End Sub

A questo punto, tuttavia, solo per onestà verso l'incauto programmatore alle prime armi, occorre fare una osservazione:

nonostante le apparenze il calcolatore è assolutamente incapace di generare una vera e propria sequenza di numeri casuali. Infatti ad ogni avvio del programma potremo notare che al lancio della routine la sequenza di numeri casuali si ripete inevitabilmente. Provare per credere!

Ho scritto questa routine che è simile a quella appena vista:

Sub Generatore_di_Numeri_pseudoCasuali()
Dim Valmax, C, R
Dim CL As Object
C = Range("a1").CurrentRegion.Columns.Count + 1
Valmax = 120
For R = 1 To 20
Cells(R, C) = Int(Rnd() * Valmax + 1)
Next
End Sub

Io personalmente ho svolto degli esperimenti in tal senso mandandola in esecuzione più volte. Ho chiuso Excel e l'ho riaperto più volte mandando in esecuzione la stessa routine.

Ogni volta ottenevo questa esquenza:

85, 65, 70, 35, 37, 93, 2, 92, 98, 86, 6, 50, 104, 95, 45, 116, 105, 7, 114, 44

Per ovviare a questo "inconveniente" ci sarebbe una soluzione usando l'istruzione Randomize().

Questa funzione può avere un argomento oppure no. Come argomento possiamo passare un numero per inizializzare il generatore di numeri casuali della funzione Rnd, assegnandogli un nuovo valore di inizializzazione. Ma, passandogli sempre lo stesso numero, otterremo solo di cambiare la base dei numeri pseudocasuali.

Ma se il numero viene omesso, come nuovo valore di inizializzazione verrà utilizzato il valore restituito dal timer di sistema, che, come facilmente intuibile, è sempre diverso, e con questo valore possiamo dire che veramente il generatore di numeri casuali viene inizializzato sempre ad un nuovo valore.

Potrebbe essere questa una possibile soluzione:

Sub Generatore_di_Numeri_Casuali()
Dim Valmax, C, R
Dim CL As Object
C = Range("a1").CurrentRegion.Columns.Count + 1
Valmax = 120
Randomize (1)
For R = 1 To 20
Cells(R, C) = Int(Rnd() * Valmax + 1)
Next
End Sub

Questa pagina perchè, se dovessimo imbatterci in un problema coi numeri casuali, possiamo sapere come comportarci.