› Sviluppare funzionalita su Microsoft Office con VBA › Come estrarre numeri e testo in modo casuale
-
AutoreArticoli
-
Alcune volte mi sono trovato nella necessità di estrarre un numero a caso prelevandolo da una lista di numeri disordinati (immaginate il sacchetto con i numeri della tombola). L'estrazione casuale non deve più considerare il numero appena uscito e quindi i numeri estratti non devono essere reinseriti nella lista... [Leggi tutto al seguente link: https://www.excelvba.it/forumexcel/come-estrarre-numeri-e-testo-in-modo-casuale/]
Ciao VF
C'è qualcosa che non capisco penso sia un errore ma potrei sbagliare. Mi sono fermato al primo caso.
Quando generi il vettore iniziale
For i = min To max lista(i - min + 1) = i Next`Stai generando un vettore che contiene i numeri e con un suo indice che andra da 1 a max -min +1 (ovvero il numero di elementi)
(i - min + 1) per i = min value 1 (i - min + 1) per i = max value max-min+1Quando poi fai lo swop generi r1 e r2 che variano tra max e min
r1 = Int(Rnd * (max - min) + min) r2 = Int(Rnd * (max - min) + min)Successivamente
tmp = lista(r1) lista(r1) = lista(r2) lista(r2) = tmppertanto il range di R1 e R2 in tutti i casi in cui min è diverso da 1 sara diverso dalk range dell'indice del vettore.
Ho ragione? Penso che tu sia partito tra 0 e Max tant'è che è rimasto anche un
ReDim lista(1 To max) As LongLa soluzione è usare un sistema tipo nell'esempio due in cui r1 e r2 vengono calcolati sulla base dell Ubound di Lista
Ciao VF
se dovessi pensare ad una estrazione "tipo tombola" io l'avrei generata esattamente estraendo un valore alla volta e poi non considerandolo più
pertanto avrei pensato a qualcosa del genere:
Sub LTgenera_lista_univoca_from_to() Dim lista() As Long Dim i As Integer Dim r1 As Long Dim r2 As Long Dim tmp As Long Dim min As Long Dim max As Long min = 100 max = 110 Randomize Timer If min > max Then min = 1 ReDim lista(1 To max - min + 1) 'genera la lista di numeri consecutivi tra min e max For i = min To max lista(i - min + 1) = i Next For i = 1 To UBound(lista, 1) r1 = Int(Rnd * ((max - min + 1) - i + 1) + i) r2 = i 'swap tmp = lista(r1) lista(r1) = lista(r2) lista(r2) = tmp Next End SubL'ho trasformata in sub per facilità di debug.
Praticamente invece di far ciclare 1000 volte ho pensato di far ciclare tante volte quante è il numero di elementi.
L'elemento selezionato all'i-esimo ciclo vine spostato alla i-esima posizione e al ciclo successivo vado a considerare solo gli elementi superiori alla i+1-esima posizione.
Personalmente anziché fare uno swop avrei generato un vettore di appoggio ma la tua soluzione è più semplice ed elegante.
Ciao
Luca
Ma certamente.
L'elemento selezionato all'i-esimo ciclo vine spostato alla i-esima posizione
Questa poi è una tecnica consolidata, che conosco, e va benissimo 🙂 Che dirti, facevo l'esempio della tombola ma tant'è, il codice anzitutto è frutto di diverse passate a partire da qualche anno fa, e poi non è ottimizzato proprio per la tombola, quello era un esempio che mi è venuto in mente. Infine, è abbastanza chiaro che ci sono tante soluzioni a qualsiasi problema.
Sull'osservazione del primo post, è più che pertinente: è plausibile che salti fuori un errore quando riadatti dei codici vecchi, non sai mai che filosofia ci stava dietro, anche se sono tuoi. A dirla tutta quando ho steso l'articolo puntavo di più sulla funzione principale, che è listRandom().
Guardandola meglio è evidente l'ingenuità sopratutto della generazione di mille estrazioni casuali per il riordino
-
AutoreArticoli
