Pregunta

Necesito generar un entero aleatorio entre 1 y n (donde n es un número entero positivo) para el uso de una unidad de prueba.No necesito algo demasiado complicado para garantizar la verdadera aleatoriedad - sólo un anticuado número aleatorio.

Cómo iba yo a hacer eso?

¿Fue útil?

Solución

Para obtener un valor entero aleatorio entre 1 y N (inclusive) puede utilizar el siguiente.

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

Otros consejos

Como se ha señalado muchas veces, la sugerencia de escribir código como este es problemático:

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 razón es que el constructor de la Random la clase proporciona una semilla por defecto basado en el reloj del sistema.En la mayoría de los sistemas, esto ha limitado la granularidad -- en algún lugar en las proximidades de 20 ms.Así que si usted escribe el siguiente código, usted va a obtener el mismo número un montón de veces en una fila:

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

El siguiente código se refiere a este tema:

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

Tiré juntos un programa simple de usar ambos métodos para generar 25 enteros aleatorios entre 1 y 100.Aquí está el resultado:

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

Uso Sistema.Al azar:

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)

Todas las respuestas hasta el momento tiene problemas o bugs (en plural, no sólo uno).Voy a explicar.Pero primero quiero felicitar a Tao Dan una idea de utilizar una variable estática para recordar el Generador variable por lo que llamar varias veces no volverá a repetir la misma # más y más, además de que dio una muy buena explicación.Pero su código sufrido el mismo error que la mayoría de los demás, como voy a explicar ahora.

MS hizo su método Next() bastante extraño.el Min parámetro es el incluido como mínimo, como sería de esperar, pero el Max parámetro es el exclusivo máximo, ya que NO sería de esperar.en otras palabras, si usted pasa min=1 max y=5, a continuación, sus números aleatorios sería de 1, 2, 3, o 4, pero nunca incluiría 5.Este es el primero de los dos errores potenciales en todo el código que utiliza Microsoft Azar.Método Next ().

Para un simple respuesta (pero todavía con otros posibles, pero raras problemas), entonces usted tendría que usar:

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

(Me gusta usar Int32 en lugar de Integer porque hace más claro lo grande que es el de int es, además de que es más corto, pero traje a ti mismo.)

Veo dos posibles problemas con este método, pero será conveniente (y correcta) para la mayoría de usos.Así que si quieres un simple la solución, creo que esto es correcto.

Sólo el 2 problemas que veo con esta función es:1:cuando Max = Int32.MaxValue así que la adición de 1 crea un desbordamiento numérico.aunque, esto sería muy raro, es una posibilidad.2:cuando min > max + 1.cuando min = 10 y max = 5, entonces la Siguiente función devuelve un error.esto puede ser lo que usted desea.pero no puede ser cualquiera.o considerar al min = 5 y max = 4.mediante la adición de 1, 5 se pasa al Siguiente método, pero no tira un error, cuando en realidad es un error, pero Microsoft .NET de código que he probado devuelve 5.así que realmente no es un "exclusivo" de max max = min.pero cuando max < min para el Azar.Next() función, entonces se produce ArgumentOutOfRangeException.así que la implementación de Microsoft es realmente inconsistente y buggy demasiado en este sentido.

usted puede simplemente quieres intercambiar los números cuando min > max entonces no se produce ningún error, sino que depende totalmente de lo que se desea.si quieres un error en valores no válidos, entonces es probable que sea mejor para tirar el error cuando Microsoft exclusivo de máximo (max + 1) en nuestro código es igual a mínimo, donde MS no de error en este caso.

el manejo de un trabajo en torno a si max = Int32.MaxValue es un poco incómodo, pero espero publicar un minucioso de la función que se encarga tanto de estas situaciones.y si quieres un comportamiento diferente de cómo lo programé, traje a ti mismo.pero hay que ser conscientes de estos 2 temas.

Feliz codificación!

Editar:Así que necesitaba un entero aleatorio generador, y decidí que el código es "derecho".Así que si alguien quiere la funcionalidad completa, aquí está uno que realmente funciona.(Pero no gana el más simple premio con sólo 2 líneas de código.Pero no es realmente complejo bien).

''' <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
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

Ejemplo De Microsoft Función Rnd

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

1 - Inicializar el generador de números aleatorios.

Randomize()

2 - Generar valor aleatorio entre 1 y 6.

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

Si usted está usando José de la respuesta, que es una gran respuesta, y de ejecutar estos espalda con espalda como este:

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

A continuación, el resultado podría volver por el mismo una y otra porque los procesos de la llamada tan rápidamente.Esto no puede haber sido un problema en el '08, pero dado que los procesadores son mucho más rápidos hoy en día, la función de no permitir que el sistema de reloj de tiempo suficiente para cambiar de antes de hacer la segunda llamada.

Desde el Sistema.Aleatorio (), la función está basado en el reloj del sistema, necesitamos permitir suficiente tiempo para que se cambie antes de la siguiente convocatoria.Una forma de lograr esto es para pausar el subproceso actual de 1 milisegundo.Véase el siguiente ejemplo:

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

Usted debe crear un generador de números pseudoaleatorios, sólo una vez:

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

Entonces, si un entero es suficiente para sus necesidades, usted puede utilizar:

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

como tantas veces como quieras.El uso de la función de contenedor sólo se justifica debido a que el valor máximo es de exclusiva - sé que los números aleatorios de trabajo de esta manera, pero la definición de .El siguiente es confuso.

La creación de un generador cada vez que necesite un número es en mi opinión equivocada;los números pseudo-aleatorios no funcionan de esta manera.

En primer lugar, el problema con la inicialización, que ha sido discutido en el otro responde.Si inicializa una vez, usted no tiene este problema.

Segundo, no estoy del todo seguro de que usted obtenga una secuencia válida de números aleatorios;en lugar, usted consigue una colección de la primera serie de múltiples secuencias diferentes que son sembradas de forma automática basándose en el tiempo con la computadora.No estoy seguro de que estos números van a pasar las pruebas que confirman la aleatoriedad de la secuencia.

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

Apenas para la referencia, VB NET Fuction de la definición para el RND y RANDOMIZE (que debería dar el mismo resultado de BÁSICA (años 1980) y todas las versiones posteriores a es:

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

Mientras que el Azar de la CLASE es:

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
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] Esta es la mejor manera, desde el principio :P

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top