65 votes

Aléatoire Int dans VB.Net

J'ai besoin de générer de l'aléatoire entier compris 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 un vieux jeu de nombres aléatoires.

Comment dois-je procéder?

82voto

Dan Tao Points 60518

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 l' Random classe fournit une racine par défaut basé 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

66voto

Kibbee Points 36474

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

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

37voto

Joseph Sturtevant Points 6597

L'Utilisation Du 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)

4voto

Bill the Lizard Points 147311
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

4voto

Shawn Kovac Points 424

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 la inclusif minimum comme on pouvait s'y attendre, mais le paramètre Max est l' exclusive 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 une 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 d' 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 une simple 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X