Question

J'ai besoin de générer un nombre entier aléatoire entre 1 et n (où n est un nombre entier positif) à utiliser pour un test unitaire.Je n'ai pas besoin de quelque chose de trop compliqué pour assurer une véritable caractère aléatoire de l' - juste une ancienne de nombre aléatoire.

Comment dois-je procéder?

Était-ce utile?

La solution

Pour obtenir une valeur entière aléatoire entre 1 et N (inclus) vous pouvez utiliser ce qui suit.

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

Autres conseils

Comme cela a été souligné à de nombreuses reprises, la suggestion d'écrire du code comme ceci est problématique:

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 raison en est que le constructeur de la Random la classe fournit un défaut de semences de base sur l'horloge du système.Sur la plupart des systèmes, ce qui a limité la granularité quelque part dans le voisinage de 20 ms).Donc, si vous écrivez le code suivant, vous allez obtenir le même nombre un tas de fois dans une rangée:

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

Le code suivant traite de cette question:

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

J'ai jeté un programme simple en utilisant les deux méthodes pour générer des 25 entiers aléatoires entre 1 et 100.Voici le résultat:

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

Utilisation Système.Aléatoire:

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)

Toutes les réponses jusqu'à présent ont des problèmes ou des bugs (au pluriel, et non un seul).Je vais vous expliquer.Mais d'abord, je tiens aussi à remercier Dan Tao l'intuition d'utiliser une variable statique pour rappeler le Générateur variable afin de l'appelant plusieurs fois de ne pas répéter le même # de plus de et plus, il a donné une très belle explication.Mais son code subi le même défaut que la plupart des autres ont, comme je l'ai expliquer maintenant.

MS fait leur méthode Next() plutôt étrange.le paramètre Min est l'insertion sur le minimum que l'on attend, mais le paramètre Max est le exclusif le maximum qu'on ne s'attendrait PAS.en d'autres termes, si vous passez min=1 et max=5 alors votre de nombres aléatoires serait de 1, 2, 3, ou 4, mais il ne serait jamais 5.C'est le premier de deux bugs potentiels dans l'ensemble du code qui utilise Microsoft est de l'Aléatoire.La méthode Next ().

Pour un simple réponse (mais toujours avec d'autres possibles, mais rares problèmes) alors vous devrez utiliser:

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

(J'aime utiliser Int32 plutôt que de Integer parce qu'il est plus clair de comment grand que l'int est, en plus, c'est plus court à taper, mais qui vous conviennent.)

Je vois deux problèmes potentiels avec cette méthode, mais il sera adapté (et corriger) pour la plupart des utilisations.Donc, si vous voulez un simple la solution, je crois que c'est correct.

Les 2 seuls problèmes que je rencontre avec cette fonction sont:1:quand Max = Int32.MaxValue ainsi, l'ajout de 1 crée un dépassement numérique.bien, ce serait rare, il est toujours une possibilité.2:lorsque min > max + 1.lorsque min = 10 et max = 5 alors la fonction Suivante renvoie une erreur.c'est peut être ce que vous voulez.mais il ne peut pas l'être non plus.ou considérer lors de la min = 5 et max = 4.par l'ajout de 1, 5 est passé à la méthode Suivante, mais il ne génère pas une erreur, quand il est vraiment une erreur, mais Microsoft .NET code que j'ai testé renvoie 5.donc, c'est vraiment pas un "exclusif" max quand le max = min.mais quand max < min pour le Hasard.Fonction Next (), puis il jette un ArgumentOutOfRangeException.si l'implémentation Microsoft est vraiment incohérent et buggy trop à cet égard.

vous pouvez simplement échanger les numéros lorsque min > max si aucune erreur n'est levée, mais cela dépend entièrement de ce qui est souhaité.si vous voulez une erreur sur les valeurs non valides, alors il est probablement mieux également jeter l'erreur lorsque Microsoft exclusif maximum (max + 1) dans notre code est égal minimum, où l'état membre n'a pas d'erreur dans ce cas.

la manipulation d'un travail autour de pour quand max = Int32.MaxValue est un peu gênant, mais je m'attends à un post approfondie de la fonction qui gère à la fois de ces situations.et si vous voulez un comportement différent de la façon dont j'ai codé il, costume vous-même.mais être conscient de ces 2 questions.

Amusez-vous bien!

Edit:J'ai donc besoin d'un nombre entier aléatoire générateur, et j'ai décidé de coder un "droit".Donc, si quelqu'un veut de l'ensemble des fonctionnalités, en voici une qui fonctionne réellement.(Mais il ne gagne pas le plus simple prix avec seulement 2 lignes de code.Mais ce n'est pas très complexe non plus.)

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

Exemple De Microsoft Fonction Rnd

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

1 - Initialiser le générateur de nombres aléatoires.

Randomize()

2 - Générer une valeur aléatoire entre 1 et 6.

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

Si vous utilisez Joseph réponse, qui est une grande réponse, et de l'exécution de ces dos-à-dos comme ceci:

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

Ensuite, le résultat pourrait revenir au même, encore et parce qu'il traite l'appel si rapidement.Cela peut ne pas avoir été un problème dans '08, mais puisque les processeurs sont beaucoup plus rapides aujourd'hui, la fonction ne permet pas le système de l'horloge suffisamment de temps pour changer avant de prendre le deuxième appel.

Depuis le Système.Random() la fonction est basée sur l'horloge du système, nous avons besoin de suffisamment de temps pour elle de changer avant le prochain appel.Une façon d'accomplir ceci est à mettre en pause le thread en cours de 1 milliseconde.Voir l'exemple ci-dessous:

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

Vous devez créer un générateur de nombres pseudo aléatoires qu'une seule fois:

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

Ensuite, si un nombre entier suffit à vos besoins, vous pouvez utiliser:

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

autant de fois que vous le souhaitez.À l'aide de la fonction wrapper n'est justifiée que parce que la valeur maximale est exclusive - je sais que les nombres aléatoires de travail de cette façon, mais la définition de l' .La prochaine est source de confusion.

Création d'un générateur à chaque fois que vous avez besoin d'un numéro est à mon avis erroné;les nombres pseudo-aléatoires ne fonctionnent pas de cette façon.

Tout d'abord, vous obtenez le problème avec l'initialisation, qui a été discuté dans les autres réponses.Si vous initialisez une fois, vous n'avez pas ce problème.

Deuxièmement, je ne suis pas du tout certain que vous obtenez un valide séquence de nombres aléatoires;au contraire, vous obtenez une collection de le premier numéro de multiples et différentes séquences qui sont placées automatiquement sur la base de l'ordinateur.Je ne suis pas certain que ces chiffres vont passer les tests qui confirment le caractère aléatoire de la séquence.

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

Juste pour la référence, VB NET Fuction définition du RND et ALÉATOIRE, et qui devrait donner les mêmes résultats de BASE (années 1980) et toutes les versions après est:

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

Tandis que le Hasard de CLASSE est:

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] Ce son de la meilleure façon, à partir de zéro :P

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top