Numero intero casuale in VB.NET


50

Ho bisogno di generare un numero intero casuale compreso tra 1 e n (dove n è un numero intero positivo) da utilizzare per un test unitario. Non ho bisogno di qualcosa di troppo complicato per assicurare la casualità vera - solo un numero casuale vecchio stile.

Come faccio?

49

Per ottenere un valore intero casuale compreso tra 1 e N (incluso) è possibile utilizzare quanto segue.

CInt(Math.Ceiling(Rnd() * n)) + 1 
+6

* "tra 1 e N (incluso)" * errato, restituirà un valore compreso tra '0' e' N'. 'Math.Ceiling (0)' è '0'. 18 lug. 122012-07-18 21:09:58

+5

Rnd() può restituire 0. Se questo accade anche quando n> 0, il risultato sarebbe 0. Quindi questo darebbe un bug molto sgradevole, specialmente perché è così raro. se vuoi il codice bacato, allora usa questo. La documentazione MS riporta: "La funzione Rnd restituisce un valore inferiore a 1, ma maggiore o uguale a zero." http://msdn.microsoft.com/en-us/library/f7s023d2(v=vs.90).aspx 30 gen. 142014-01-30 15:10:17

+4

Provato così com'è e eseguito in istanza di 12 quando si utilizza n = 11. Non incluso. MSDN ha un esempio migliore: randomValue = CInt (Math.Floor ((upperbound - lowerbound + 1) * Rnd())) + lowerbound 19 dic. 142014-12-19 18:27:57


4
Public Function RandomNumber(ByVal n As Integer) As Integer 
    'initialize random number generator 
    Dim r As New Random(System.DateTime.Now.Millisecond) 
    Return r.Next(1, n) 
End Function 
+2

se si desiderano errori, quindi utilizzare questo codice. MS ha reso il loro metodo Next() piuttosto strano. il parametro Min è il minimo compreso come ci si aspetterebbe, ma il parametro Max è il massimo esclusivo come NON ci si aspetterebbe. in altre parole, se si passa min = 1 e max = 5, i numeri casuali saranno uno qualsiasi di 1, 2, 3 o 4, ma non includeranno mai 5. 30 gen. 142014-01-30 16:31:00

+4

@ShawnKovac Ecco come vengono implementati generatori di numeri casuali. 30 gen. 142014-01-30 17:53:28


32

Uso System.Random:

Dim MyMin As Integer = 1, MyMax As Integer = 5, My1stRandomNumber As Integer, My2ndRandomNumber As Integer 

' Create a random number generator 
Dim Generator As System.Random = New System.Random() 

' Get a random number >= MyMin and <= MyMax 
My1stRandomNumber = Generator.Next(MyMin, MyMax + 1) ' Note: Next function returns numbers _less than_ max, so pass in max + 1 to include max as a possible value 

' Get another random number (don't create a new generator, use the same one) 
My2ndRandomNumber = Generator.Next(MyMin, MyMax + 1) 
+5

Sembra più semplice con ritorno New Random(). Next (minValue, maxValue) 02 feb. 102010-02-02 10:25:35

+2

True. Tuttavia, se l'utente volesse una sequenza di numeri casuali (piuttosto che uno solo), vorrebbe trattenere il riferimento casuale. 03 feb. 102010-02-03 00:01:01

+1

Cambia 'Dim Generator' in' Generatore statico' e hai un'istanza su cui puoi aggrapparti (non un thread-safe, ma ciò non avrà importanza nella maggior parte degli scenari realistici). 20 apr. 102010-04-20 18:50:54

+1

sembra più semplice, ma questo codice è assolutamente sbagliato. se vuoi un bug, usa questo codice. MS ha reso il loro metodo Next() piuttosto strano. il parametro Min è il minimo compreso come ci si aspetterebbe, ma il parametro Max è il * esclusivo * minimo come non ci si aspetterebbe. in altre parole, se passi min = 1 e max = 5 allora i tuoi numeri casuali sarebbero uno qualsiasi di 1, 2, 3 o 4, ma non includeranno mai 5. 30 gen. 142014-01-30 15:15:01

  0

@ShawnKovac - Buona presa. Non avevo notato la discrepanza inclusiva/esclusiva tra i parametri min e max di Random.Next. Esempio di codice aggiornato. 01 feb. 142014-02-01 19:27:29


61

Come è stato sottolineato più volte, il suggerimento di scrivere codice come questo è problematico:

Public Function GetRandom(ByVal Min As Integer, ByVal Max As Integer) As Integer 
    Dim Generator As System.Random = New System.Random() 
    Return Generator.Next(Min, Max) 
End Function 

La ragione è che il costruttore per la classe Random fornisce un seme predefinito basato sull'orologio del sistema. Sulla maggior parte dei sistemi, questo ha una granularità limitata, da qualche parte in prossimità di 20 ms. Quindi, se si scrive il codice seguente, si sta andando ad ottenere lo stesso numero di un mucchio di volte di fila:

Dim randoms(1000) As Integer 
For i As Integer = 0 to randoms.Length - 1 
    randoms(i) = GetRandom(1, 100) 
Next 

I seguenti indirizzi di codice questo numero:

Public Function GetRandom(ByVal Min As Integer, ByVal Max As Integer) As Integer 
    ' by making Generator static, we preserve the same instance ' 
    ' (i.e., do not create new instances with the same seed over and over) ' 
    ' between calls ' 
    Static Generator As System.Random = New System.Random() 
    Return Generator.Next(Min, Max) 
End Function 

ho buttato insieme una semplice programma utilizzando entrambi i metodi per generare 25 numeri interi casuali compresi tra 1 e 100. Qui l'output:

Non-static: 70 Static: 70 
Non-static: 70 Static: 46 
Non-static: 70 Static: 58 
Non-static: 70 Static: 19 
Non-static: 70 Static: 79 
Non-static: 70 Static: 24 
Non-static: 70 Static: 14 
Non-static: 70 Static: 46 
Non-static: 70 Static: 82 
Non-static: 70 Static: 31 
Non-static: 70 Static: 25 
Non-static: 70 Static: 8 
Non-static: 70 Static: 76 
Non-static: 70 Static: 74 
Non-static: 70 Static: 84 
Non-static: 70 Static: 39 
Non-static: 70 Static: 30 
Non-static: 70 Static: 55 
Non-static: 70 Static: 49 
Non-static: 70 Static: 21 
Non-static: 70 Static: 99 
Non-static: 70 Static: 15 
Non-static: 70 Static: 83 
Non-static: 70 Static: 26 
Non-static: 70 Static: 16 
Non-static: 70 Static: 75 
  0

penso che questo non genererà mai effettivamente "100". tra min e meno di MaxValue effettivamente (credo) 11 apr. 122012-04-11 13:29:47

+1

@maxhodges: Sì, penso che tu abbia ragione. C'è una sfortunata ambiguità nella parola "tra"; Non so se l'OP si preoccupa se 100 è incluso o meno. Non l'ho fatto, personalmente; la mia risposta era intesa solo per illustrare la condivisione di un oggetto 'Random' tra più chiamate di funzione usando la parola chiave' Static'. 11 apr. 122012-04-11 13:56:03

  0

Ho scoperto che avevo bisogno di fare riferimento a questo codice più di una volta. Grazie! 30 giu. 132013-06-30 17:53:33

  0

Vorrei fare +1 su di te per l'analisi statistica, ma il codice è bacato. ma complimenti per quella intuizione statica!e io ti -1 per una risposta buggata. ma loro persino fuori. 30 gen. 142014-01-30 15:24:08

+3

se si desidera un errore, quindi utilizzare questo codice. MS ha reso il loro metodo Next() piuttosto strano. il parametro Min è il minimo compreso come ci si aspetterebbe, ma il parametro Max è il minimo esclusivo come NON ci si aspetterebbe. in altre parole, se passi min = 1 e max = 5 allora i tuoi numeri casuali sarebbero uno qualsiasi di 1, 2, 3 o 4, ma non includeranno mai 5. 30 gen. 142014-01-30 15:24:52

+1

@ShawnKovac: Posso apprezzare che può essere sorprendente . Ma chiamarlo "buggy" è un po 'eccessivo, secondo me; semplicemente non era il comportamento * che * ti aspettavi. La verità è che la maggior parte delle implementazioni di numeri casuali (che io conosca) funzionano in questo modo: limite inferiore compreso, limite superiore esclusivo. Può essere utile in molti casi d'uso comuni, come selezionare un oggetto casuale da un array (dove si seleziona l'elemento tra '0' e' array.length'). 30 gen. 142014-01-30 15:37:26

  0

Ad esempio: ['Random.nextInt'] (http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextInt (int)) in Java, [' Math. random'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) in JavaScript, ['rand'] (http: //www.ruby-doc .org/core-2.1.0/Random.html # method-i-rand) in Ruby, ecc. 30 gen. 142014-01-30 15:39:11

  0

grazie Dan. Apprezzo quel feedback. è alquanto scomodo, e poi vedo i programmatori che pensano che "minimo" e "massimo" hanno una somiglianza coerente come essere inclusivi ed esclusivi ... sì, come vorrei. ma questo è umano. così tante "stranezze" nella programmazione è il motivo per cui la programmazione è così complicata. e abbiamo solo bisogno di scrivere un codice migliore. apprezzo il tuo feedback. Grazie. 30 gen. 142014-01-30 16:37:05

  0

credo che quello che chiamerei non buggy né bizzarro, ma anche il codice di qualità è se le variabili fossero semplicemente nominate per riflettere * chiaramente * quali sono: incMin e excMax sarebbero nomi brevi fattibili. :) e forse un commento che incMin = minimo compreso & excMax = massimo esclusivo. 30 gen. 142014-01-30 16:37:53

  0

@dantao: apprezzo molto il tuo feedback. grazie per avermi aperto un po 'di più (almeno tanto quanto mi permetto di vederlo in un altro modo). ;) Ho chiamato le mie variabili nel mio 'codice fisso' in modo che altri programmatori che potrebbero vedere il mio codice in seguito non sarebbero confusi se si aspettassero questo comportamento 'bizzarro' (che per me, sento ancora che sia bacato perché è non un uso coerente di entrambi i parametri sia inclusivi che esclusivi). il mio metodo usa limiti inclusivi per entrambi i parametri, che consente anche il massimo, gamma completa di un int come risultato, che è come ritengo debba essere codificato. 30 gen. 142014-01-30 16:47:38

  0

@ShawnKovac: Non sei solo. Python's ['random.randint'] (http://docs.python.org/2/library/random.html#random.randint), ad esempio, è inclusivo su entrambe le estremità. E sono d'accordo con te sul fatto che i nomi delle variabili 'min' e' max' dovrebbero essere probabilmente più espliciti (in effetti puoi vedere che cito l'ambiguità del mio precedente commento da aprile 2012!). Immagino che una delle domande più complicate quando si progetta un'interfaccia è questa: si cerca di renderlo intuitivo "nel vuoto" o attingi alle aspettative degli sviluppatori da ciò che è venuto prima? 30 gen. 142014-01-30 16:52:11

  0

@ShawnKovac: l'indicizzazione dell'array basato su 0 è un esempio perfetto. Probabilmente non è "intuitivo" (per alcuni, almeno all'inizio), ma è talmente diffuso che ora, se dovessi creare un nuovo linguaggio che usasse l'indicizzazione basata su 1, avresti * sorpreso * un sacco di sviluppatori. Quindi l'intuitivo può diventare intuitivo sulla base dell'esperienza precedente. Il mio feeling con 'Random.Next' in .NET è che si trova da qualche parte in un'area grigia. Un sacco di sviluppatori (come te) sicuramente lo trovano sorprendente, ma immagino che ce ne siano anche alcuni che si aspettano esattamente il comportamento che ha. 30 gen. 142014-01-30 16:54:48

  0

sì, capisco il catering per invertire l'uso. è divertente che stavo pensando all'indice massimo di VB quando dichiaro che un array è contro-intuitivo a causa della dichiarazione di "stile C" atteso che è così comune. ma hai ragione, l'immagine più grande è l'intero problema di indicizzazione 0. hai ragione. ora ci siamo abituati e sarebbe più scomodo usare l'indicizzazione basata su 1 ... ora che sono abituato. quale credo sia esattamente il tuo punto. grazie per questi punti e condividere la tua saggezza! Anche il metodo Instr() di VB è un buon esempio con l'indicizzazione basata su 1. beh, immagino che una cosa sia certa con il tempo. :) 30 gen. 142014-01-30 17:01:53

  0

Ho modificato la funzione come segue: pubblica GetRandom Function (ByVal Min As Integer, ByVal Max As Integer) As Integer 'facendo Generator statico, conserviamo la stessa istanza' '(vale a dire, non creare nuova istanze con lo stesso seme ripetutamente) ' ' tra le chiamate ' Generatore statico As System.Random = New System.Random() Dim Risultato come numero intero = Generatore.Next (Min, Max) se Result = Max then result - = 1 End Function I passaggio quindi a un valore superiore a quello massimo desiderato (ad esempio se si desidera un massimo di 255, si passa a 256 come massimo). 24 nov. 162016-11-24 17:40:16


-5
Function xrand() As Long 
     Dim r1 As Long = Now.Day & Now.Month & Now.Year & Now.Hour & Now.Minute & Now.Second & Now.Millisecond 
     Dim RAND As Long = Math.Max(r1, r1 * 2) 
     Return RAND 
End Function 

[BBOYSE] Questo è il modo migliore, partendo da zero: P

+3

questo è orribile. non è affatto casuale. è solo un numero precalcolato basato sul tempo. questo non mostrerebbe alcuna proprietà di un numero casuale. in più non risponde alla domanda. la domanda non era come generare un numero casuale ma uno tra 1 e un valore dato. 30 gen. 142014-01-30 15:33:20


1

Se si utilizza la risposta di Joseph, che è una grande risposta, e si esegue questi back to back in questo modo:

dim i = GetRandom(1, 1715) 
dim o = GetRandom(1, 1715) 

Poi il il risultato potrebbe tornare lo stesso più e più volte perché elabora la chiamata così rapidamente. Questo potrebbe non essere stato un problema nel 2008, ma poiché i processori sono molto più veloci oggi, la funzione non consente all'orologio di sistema il tempo sufficiente per cambiare prima di effettuare la seconda chiamata.

Poiché la funzione System.Random() si basa sull'orologio di sistema, è necessario consentire il tempo necessario affinché cambi prima della successiva chiamata. Un modo per ottenere ciò è mettere in pausa il thread corrente per 1 millisecondo. Vedere il seguente esempio:

Public Function GetRandom(ByVal min as Integer, ByVal max as Integer) as Integer 
    Static staticRandomGenerator As New System.Random 
    max += 1 
    Return staticRandomGenerator.Next(If(min > max, max, min), If(min > max, min, max)) 
End Function 
+2

se si desidera un errore, quindi utilizzare questo codice. MS ha reso il loro metodo Next() piuttosto strano. il parametro Min è il minimo compreso come ci si aspetterebbe, ma il parametro Max è il minimo esclusivo come NON ci si aspetterebbe. in altre parole, se passi min = 1 e max = 5 allora i tuoi numeri casuali sarebbero uno qualsiasi di 1, 2, 3 o 4, ma non includeranno mai 5. 30 gen. 142014-01-30 15:26:35

  0

@ShawnKovac Grazie per avermi illuminato riguardo a. funzione che non restituisce il numero massimo e l'uso dell'oggetto statico system.random (anche se il nome Min e Max probabilmente non sono più appropriati poiché questo è solo un intervallo: da A a B). Ho fatto un test e le prestazioni dei due sono uguali. Inoltre, io uso il numero intero invece di int32 perché è attualmente legato a int32 (rendendoli quasi identici) e poiché faccio molto lavoro in SQL, mi piace la sintassi e non mi dispiace digitare la 'e' prima del mio ' scheda '. (A ciascuno il proprio però.) ~ Cheers 21 mar. 142014-03-21 19:16:04

  0

grazie per aver cura di correggere il codice. sei ben al di là di molte altre persone in questo. Sì, Int32 e Integer producono lo stesso effetto, per quanto ne so, esattamente lo stesso. Tranne che per me, Int32 è più chiaro, per le persone che non sanno che dimensione di Integer è un 'Ingeger'. Questa è la ragione principale per cui utilizzo Int32. Ma capisco che è assolutamente una cosa preferenziale. 27 mar. 142014-03-27 16:06:56

  0

Mi piace anche l'alias Int32 più breve, e sì, con intelligenza la digitazione è quasi uguale. Ma mi piace anche la lettura più compatta. Ma quando codice C#, mi piace ancora usare il più specifico Int32 piuttosto che il suo 'int' ancora più breve nel caso in cui i neofiti guardino il mio codice, per il bene della chiarezza altrui. Ma a ciascuno il suo. :) 27 mar. 142014-03-27 16:08:35

  0

Voglio solo far notare che il tuo codice eseguirà un bug out o genererà un errore se max = Integer.MaxValue. Ovviamente, questo di solito non ha importanza, ma se volessi eliminare quel potenziale problema, puoi vedere la mia risposta dove ho fornito una soluzione per fornire l'intera gamma di Int casuale, se l'utente volesse includere Integer.MaxValue. Sfortunatamente, Microsoft non ha reso facile avere un codice molto robusto per questo quando hanno implementato quella che io chiamo una funzione casuale estremamente bizzarra. Il codice veramente robusto è difficile da trovare. :( 27 mar. 142014-03-27 16:11:52


5

Tutte le risposte finora hanno problemi o bug (plurale, non solo uno). Spiegherò. Ma prima voglio complimentarmi con l'intuizione di Dan Tao di usare una variabile statica per ricordare la variabile Generator, quindi chiamarla più volte non ripeterà più volte lo stesso #, e ha fornito una spiegazione molto bella. Ma il suo codice ha subito lo stesso difetto che molti altri hanno, come spiego ora.

MS ha reso il metodo Next() piuttosto strano. il parametro Min è il minimo compreso come ci si aspetterebbe, ma il parametro Max è il esclusivo massimo come non ci si aspetterebbe. in altre parole, se passi min = 1 e max = 5 allora i tuoi numeri casuali sarebbero uno qualsiasi di 1, 2, 3 o 4, ma non includeranno mai 5.Questo è il primo di due potenziali bug in tutto il codice che utilizza il metodo Random.Next() di Microsoft.

Per una semplice risposta(ma ancora con altri possibili problemi, ma rare), allora avresti bisogno di usare:

Private Function GenRandomInt(min As Int32, max As Int32) As Int32 
    Static staticRandomGenerator As New System.Random 
    Return staticRandomGenerator.Next(min, max + 1) 
End Function 

(mi piace usare Int32 piuttosto che Integer perché rende più chiaro quanto è grande l'int è, più è più breve da digitare, ma si adatta.)

Vedo due potenziali problemi con questo metodo, ma sarà adatto (e corretto) per la maggior parte degli usi. Quindi, se vuoi una soluzione semplice, , credo che sia corretta.

Gli unici 2 problemi che vedo con questa funzione sono: 1: quando Max = Int32.MaxValue quindi l'aggiunta 1 crea un overflow numerico. tuttavia, questo sarebbe raro, è ancora una possibilità. 2: quando min> max + 1. quando min = 10 e max = 5, la funzione Next genera un errore. questo potrebbe essere quello che vuoi ma potrebbe non esserlo neanche. o considera quando min = 5 e max = 4. aggiungendo 1, 5 viene passato al metodo Next, ma non genera un errore, quando è davvero un errore, ma il codice di Microsoft .NET che ho testato restituisce 5. quindi in realtà non è un massimo 'esclusivo' quando il massimo = il minimo. ma quando max. < min per la funzione Random.Next(), genera una ArgumentOutOfRangeException. quindi l'implementazione di Microsoft è davvero incoerente e buggy anche a questo riguardo.

Si consiglia di scambiare semplicemente i numeri quando min> max in modo che non venga emesso alcun errore, ma dipende totalmente da ciò che si desidera. se vuoi un errore su valori non validi, probabilmente è meglio lanciare l'errore anche quando il massimo esclusivo di Microsoft (max + 1) nel nostro codice è uguale al minimo, dove MS non riesce ad errori in questo caso.

gestire un work-around per quando max = Int32.MaxValue è un po 'scomodo, ma mi aspetto di pubblicare una funzione approfondita che gestisca entrambe queste situazioni. e se vuoi un comportamento diverso da come lo ho codificato, adattati a te stesso. ma sii consapevole di questi 2 problemi.

Felice codifica!

Modifica: Quindi mi serviva un generatore di numeri interi casuali, e ho deciso di codificarlo 'giusto'. Quindi se qualcuno vuole la piena funzionalità, eccone uno che funziona davvero. (Ma non vincere il premio più semplice con solo 2 righe di codice, ma non è davvero complessa sia..)

''' <summary> 
''' Generates a random Integer with any (inclusive) minimum or (inclusive) maximum values, with full range of Int32 values. 
''' </summary> 
''' <param name="inMin">Inclusive Minimum value. Lowest possible return value.</param> 
''' <param name="inMax">Inclusive Maximum value. Highest possible return value.</param> 
''' <returns></returns> 
''' <remarks></remarks> 
Private Function GenRandomInt(inMin As Int32, inMax As Int32) As Int32 
    Static staticRandomGenerator As New System.Random 
    If inMin > inMax Then Dim t = inMin : inMin = inMax : inMax = t 
    If inMax < Int32.MaxValue Then Return staticRandomGenerator.Next(inMin, inMax + 1) 
    ' now max = Int32.MaxValue, so we need to work around Microsoft's quirk of an exclusive max parameter. 
    If inMin > Int32.MinValue Then Return staticRandomGenerator.Next(inMin - 1, inMax) + 1 ' okay, this was the easy one. 
    ' now min and max give full range of integer, but Random.Next() does not give us an option for the full range of integer. 
    ' so we need to use Random.NextBytes() to give us 4 random bytes, then convert that to our random int. 
    Dim bytes(3) As Byte ' 4 bytes, 0 to 3 
    staticRandomGenerator.NextBytes(bytes) ' 4 random bytes 
    Return BitConverter.ToInt32(bytes, 0) ' return bytes converted to a random Int32 
End Function 
+1

Assurdità completa. Come ha detto Bill, il comportamento di 'Next()' è del tutto normale, non "piuttosto strano" 17 set. 152015-09-17 14:39:59

  0

Per essere onesti, come "normale" come potrebbe essere per le funzioni integrate di vari linguaggi di programmazione , in realtà è piuttosto strano per il resto del mondo .Quando è l'ultima volta che hai sentito qualcuno dire 1D6 ti dà un numero compreso tra 1 e 7? Per chi non ha letto attentamente la documentazione della lingua e non ha particolare familiarità con il strano comportamento delle funzioni RNG, potrebbero essere una sorpresa e non sapere cosa è successo 28 dic. 152015-12-28 07:22:32

  0

@ Michael, mi hai perso con "1D6" dando un # tra 1 e 7. Non capisco la tua "D". anche per quanto riguarda il modo in cui Microsoft's Random.Next (min, max) funziona, il programma fornisce 1 & 7 e il metodo restituisce un # nell'intervallo 1 e 6. Quindi penso che tu fossi leggermente fuori dalla precisione esatta della tua analogia (a meno che tu non ti stia riferendo ad un altro comportamento insensato se intendevi fare riferimento a Microsoft, dico solo che il tuo piccolo mixaggio è perfettamente * normale * perché ciò che MS ha fatto non ha alcun senso logico (oltre a quello che altri hanno sottolineato: che è diventato la nuova 'norma'). 29 dic. 152015-12-29 13:09:49

  0

E sto semplicemente vocalizzando un po 'di logica che è meglio usare logicamente il minimo inclusivo e il massimo inclusivo per coerenza e rifiutare il quasi-'norm' che è iniziato. È tutto. :) 29 dic. 152015-12-29 13:11:22

  0

1D6 significa lanciare un dado a sei facce, il tipo utilizzato in molti giochi da tavolo o un gioco da tavolo. I numeri vanno da 1 a 6, inclusi, e le persone direbbero "1 a 6", non "da 1 a 7" e si presume che 7 non sia incluso. Potresti usare analogie simili da molti altri aspetti della vita. Se dico che una lega di baseball è per bambini tra 12 e 14, sto includendo sia 12 e 14. Etc. Non riesco a pensare ad un esempio pratico di escludere il limite superiore di un intervallo al di fuori di una classe matematica. 04 gen. 162016-01-04 04:57:43

  0

Ok, @ Michael, ora che capisco il tuo post, vedo che tu e io siamo completamente d'accordo. Hai appena espresso lo stesso concetto in un altro modo. Bel punto.:) Grazie per il chiarimento. 11 gen. 162016-01-11 17:55:29


0
Dim rnd As Random = New Random 
rnd.Next(n) 

1

Si dovrebbe creare un generatore di numeri pseudo-casuali solo una volta:

Dim Generator As System.Random = New System.Random() 

Poi, se un intero è sufficiente per le vostre esigenze, è possibile utilizzare:

Public Function GetRandom(myGenerator As System.Random, ByVal Min As Integer, ByVal Max As Integer) As Integer 
'min is inclusive, max is exclusive (dah!) 
Return myGenerator.Next(Min, Max + 1) 
End Function 

tutte le volte che vuoi. L'utilizzo della funzione wrapper è giustificato solo perché il valore massimo è esclusivo: so che i numeri casuali funzionano in questo modo ma la definizione di .Next è confusa.

Creare un generatore ogni volta che è necessario un numero è a mio parere sbagliato; i numeri pseudo casuali non funzionano in questo modo.

In primo luogo, si ottiene il problema con l'inizializzazione che è stato discusso nelle altre risposte.Se si inizializza una volta, non si ha questo problema.

In secondo luogo, non sono affatto sicuro che si ottenga una sequenza valida di numeri casuali; piuttosto, si ottiene una raccolta del primo numero di sequenze multiple multiple che vengono seminate automaticamente in base al tempo del computer. Non sono sicuro che questi numeri supereranno i test che confermano la casualità della sequenza.


1

Microsoft Esempio Rnd Function

https://msdn.microsoft.com/en-us/library/f7s023d2%28v=vs.90%29.aspx

1- inizializzare il generatore di numeri casuali.

Randomize() 

2 - Generare valore casuale compreso tra 1 e 6.

Dim value As Integer = CInt(Int((6 * Rnd()) + 1)) 

0

Solo per riferimento, VB definizione Fuction NET per RND e RANDOMIZE (che dovrebbe dare gli stessi risultati di BASIC (1980 anni) e tutte le versioni dopo è:

Public NotInheritable Class VBMath 
    ' Methods 
    Private Shared Function GetTimer() As Single 
     Dim now As DateTime = DateTime.Now 
     Return CSng((((((60 * now.Hour) + now.Minute) * 60) + now.Second) + (CDbl(now.Millisecond)/1000))) 
    End Function 

    Public Shared Sub Randomize() 
     Dim timer As Single = VBMath.GetTimer 
     Dim projectData As ProjectData = ProjectData.GetProjectData 
     Dim rndSeed As Integer = projectData.m_rndSeed 
     Dim num3 As Integer = BitConverter.ToInt32(BitConverter.GetBytes(timer), 0) 
     num3 = (((num3 And &HFFFF) Xor (num3 >> &H10)) << 8) 
     rndSeed = ((rndSeed And -16776961) Or num3) 
     projectData.m_rndSeed = rndSeed 
    End Sub 

    Public Shared Sub Randomize(ByVal Number As Double) 
     Dim num2 As Integer 
     Dim projectData As ProjectData = ProjectData.GetProjectData 
     Dim rndSeed As Integer = projectData.m_rndSeed 
     If BitConverter.IsLittleEndian Then 
      num2 = BitConverter.ToInt32(BitConverter.GetBytes(Number), 4) 
     Else 
      num2 = BitConverter.ToInt32(BitConverter.GetBytes(Number), 0) 
     End If 
     num2 = (((num2 And &HFFFF) Xor (num2 >> &H10)) << 8) 
     rndSeed = ((rndSeed And -16776961) Or num2) 
     projectData.m_rndSeed = rndSeed 
    End Sub 

    Public Shared Function Rnd() As Single 
     Return VBMath.Rnd(1!) 
    End Function 

    Public Shared Function Rnd(ByVal Number As Single) As Single 
     Dim projectData As ProjectData = ProjectData.GetProjectData 
     Dim rndSeed As Integer = projectData.m_rndSeed 
     If (Number <> 0) Then 
      If (Number < 0) Then 
       Dim num1 As UInt64 = (BitConverter.ToInt32(BitConverter.GetBytes(Number), 0) And &HFFFFFFFF) 
       rndSeed = CInt(((num1 + (num1 >> &H18)) And CULng(&HFFFFFF))) 
      End If 
      rndSeed = CInt((((rndSeed * &H43FD43FD) + &HC39EC3) And &HFFFFFF)) 
     End If 
     projectData.m_rndSeed = rndSeed 
     Return (CSng(rndSeed)/1.677722E+07!) 
    End Function 

End Class 

Mentre la classe Random è:

Public Class Random 
    ' Methods 
    <__DynamicallyInvokable> _ 
    Public Sub New() 
     Me.New(Environment.TickCount) 
    End Sub 

    <__DynamicallyInvokable> _ 
    Public Sub New(ByVal Seed As Integer) 
     Me.SeedArray = New Integer(&H38 - 1) {} 
     Dim num4 As Integer = If((Seed = -2147483648), &H7FFFFFFF, Math.Abs(Seed)) 
     Dim num2 As Integer = (&H9A4EC86 - num4) 
     Me.SeedArray(&H37) = num2 
     Dim num3 As Integer = 1 
     Dim i As Integer 
     For i = 1 To &H37 - 1 
      Dim index As Integer = ((&H15 * i) Mod &H37) 
      Me.SeedArray(index) = num3 
      num3 = (num2 - num3) 
      If (num3 < 0) Then 
       num3 = (num3 + &H7FFFFFFF) 
      End If 
      num2 = Me.SeedArray(index) 
     Next i 
     Dim j As Integer 
     For j = 1 To 5 - 1 
      Dim k As Integer 
      For k = 1 To &H38 - 1 
       Me.SeedArray(k) = (Me.SeedArray(k) - Me.SeedArray((1 + ((k + 30) Mod &H37)))) 
       If (Me.SeedArray(k) < 0) Then 
        Me.SeedArray(k) = (Me.SeedArray(k) + &H7FFFFFFF) 
       End If 
      Next k 
     Next j 
     Me.inext = 0 
     Me.inextp = &H15 
     Seed = 1 
    End Sub 

    Private Function GetSampleForLargeRange() As Double 
     Dim num As Integer = Me.InternalSample 
     If ((Me.InternalSample Mod 2) = 0) Then 
      num = -num 
     End If 
     Dim num2 As Double = num 
     num2 = (num2 + 2147483646) 
     Return (num2/4294967293) 
    End Function 

    Private Function InternalSample() As Integer 
     Dim inext As Integer = Me.inext 
     Dim inextp As Integer = Me.inextp 
     If (++inext >= &H38) Then 
      inext = 1 
     End If 
     If (++inextp >= &H38) Then 
      inextp = 1 
     End If 
     Dim num As Integer = (Me.SeedArray(inext) - Me.SeedArray(inextp)) 
     If (num = &H7FFFFFFF) Then 
      num -= 1 
     End If 
     If (num < 0) Then 
      num = (num + &H7FFFFFFF) 
     End If 
     Me.SeedArray(inext) = num 
     Me.inext = inext 
     Me.inextp = inextp 
     Return num 
    End Function 

    <__DynamicallyInvokable> _ 
    Public Overridable Function [Next]() As Integer 
     Return Me.InternalSample 
    End Function 

    <__DynamicallyInvokable> _ 
    Public Overridable Function [Next](ByVal maxValue As Integer) As Integer 
     If (maxValue < 0) Then 
      Dim values As Object() = New Object() { "maxValue" } 
      Throw New ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", values)) 
     End If 
     Return CInt((Me.Sample * maxValue)) 
    End Function 

    <__DynamicallyInvokable> _ 
    Public Overridable Function [Next](ByVal minValue As Integer, ByVal maxValue As Integer) As Integer 
     If (minValue > maxValue) Then 
      Dim values As Object() = New Object() { "minValue", "maxValue" } 
      Throw New ArgumentOutOfRangeException("minValue", Environment.GetResourceString("Argument_MinMaxValue", values)) 
     End If 
     Dim num As Long = (maxValue - minValue) 
     If (num <= &H7FFFFFFF) Then 
      Return (CInt((Me.Sample * num)) + minValue) 
     End If 
     Return (CInt(CLng((Me.GetSampleForLargeRange * num))) + minValue) 
    End Function 

    <__DynamicallyInvokable> _ 
    Public Overridable Sub NextBytes(ByVal buffer As Byte()) 
     If (buffer Is Nothing) Then 
      Throw New ArgumentNullException("buffer") 
     End If 
     Dim i As Integer 
     For i = 0 To buffer.Length - 1 
      buffer(i) = CByte((Me.InternalSample Mod &H100)) 
     Next i 
    End Sub 

    <__DynamicallyInvokable> _ 
    Public Overridable Function NextDouble() As Double 
     Return Me.Sample 
    End Function 

    <__DynamicallyInvokable> _ 
    Protected Overridable Function Sample() As Double 
     Return (Me.InternalSample * 4.6566128752457969E-10) 
    End Function 


    ' Fields 
    Private inext As Integer 
    Private inextp As Integer 
    Private Const MBIG As Integer = &H7FFFFFFF 
    Private Const MSEED As Integer = &H9A4EC86 
    Private Const MZ As Integer = 0 
    Private SeedArray As Integer() 
End Class