VB.NET中的随机整数

bre*_*dan 57 vb.net random

我需要生成1到n之间的随机整数(其中n是正整数),用于单元测试.我不需要过于复杂的东西来确保真正的随机性 - 只是一个老式的随机数.

我该怎么办?

Dan*_*Tao 70

正如已经多次指出的那样,编写这样的代码的建议是有问题的:

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
Run Code Online (Sandbox Code Playgroud)

原因是Random类的构造函数根据系统的时钟提供默认种子.在大多数系统中,这具有有限的粒度 - 在20毫秒附近.因此,如果您编写以下代码,您将连续多次获得相同的数字:

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

以下代码解决了此问题:

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
Run Code Online (Sandbox Code Playgroud)

我使用两种方法将一个简单的程序汇总在一起,生成25个1到100之间的随机整数.这是输出:

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
Run Code Online (Sandbox Code Playgroud)

  • 如果你想要一个bug,那么使用这个代码.MS使他们的Next()方法相当奇怪.Min参数是人们所期望的包容性最小值,但Max参数是人们不期望的唯一最小值.换句话说,如果你传递min = 1和max = 5,那么你的随机数将是1,2,3或4中的任何一个,但它永远不会包括5. (3认同)
  • @ShawnKovac:我很欣赏它可能会令人惊讶.但在我看来,把它称为"越野车"有点矫枉过正; 它只是不是你期望的行为*.事实上,大多数随机数实现(我所知道的)都是这样工作的:包含下限,独占上限.在很多常见的用例中都很方便,例如从数组中选择一个随机项(在那里选择`0`和`array.length`之间的项). (3认同)
  • @maxhodges:是的,我认为你是对的。不幸的是,“之间”这个词有一个歧义。我不知道OP是否关心是否包含100。就我个人而言,我没有;我的回答只是为了说明使用“Static”关键字在多个函数调用之间共享“Random”对象。 (2认同)

Kib*_*bee 56

要获得1到N(包括)之间的随机整数值,您可以使用以下内容.

CInt(Math.Ceiling(Rnd() * n)) + 1
Run Code Online (Sandbox Code Playgroud)

  • *"在1和N之间(包括)"*错误,将返回"0"和"N"之间的值.`Math.Ceiling(0)`是'0`. (6认同)
  • Rnd()可以返回0.如果发生这种情况,那么即使n> 0,结果也是0.因此,这会产生一个非常讨厌的错误,特别是因为它是如此罕见.如果你想要错误的代码,那么使用它.MS文档读取:"Rnd函数返回的值小于1,但大于或等于零." http://msdn.microsoft.com/en-us/library/f7s023d2(v=vs.90).aspx (5认同)
  • 当使用n = 11时,按原样尝试并运行到12的实例.不包容.MSDN有更好的例子:randomValue = CInt(Math.Floor((upperbound - lowerbound + 1)*Rnd()))+ lowerbound (5认同)

Jos*_*ant 33

使用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)
Run Code Online (Sandbox Code Playgroud)

  • 返回New Random()看起来更简单.Next(minValue,maxValue) (5认同)
  • 真正.但是,如果用户想要一系列随机数(而不仅仅是一个),他们会希望保留随机引用. (2认同)

Sha*_*vac 5

到目前为止,所有的答案都有问题或错误(复数,而不仅仅是一个).我会解释.但首先我要赞美Dan Tao的见解,使用静态变量来记住Generator变量,因此多次调用它不会重复相同的#一遍又一遍,而且他给出了一个非常好的解释.但正如我现在解释的那样,他的代码遭遇了与其他大多数人相同的缺陷.

MS使他们的Next()方法相当奇怪.Min参数是人们所期望的包容性最小值,但Max参数是人们不期望的唯一最大值.换句话说,如果你传递分钟= 1和max = 5那么你的随机数是任何的1,2,3或4,但它绝不会包括5这是所有代码的第一个两个潜在的bug使用Microsoft的Random.Next()方法.

对于一个简单的答案(但仍然有其他可能但罕见的问题),那么你需要使用:

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
Run Code Online (Sandbox Code Playgroud)

(我喜欢使用Int32而不是Integer因为它更清楚地表明int的大小,加上它的类型更短,但适合自己.)

我发现这种方法有两个潜在的问题,但对于大多数用途来说它是合适的(并且是正确的).所以如果你想要一个简单的解决方案,我相信这是正确的.

我在这个函数中看到的唯一两个问题是:1:当Max = Int32.MaxValue时,添加1会产生数字溢出.虽然这很少见,但仍有可能.2:当min> max + 1.当min = 10且max = 5时,Next函数抛出错误.这可能是你想要的.但它可能也不是.或考虑当min = 5和max = 4.通过添加1,5传递给Next方法,但它不会抛出错误,当它确实是一个错误,但我测试的Microsoft .NET代码返回5.所以当max = min时,它确实不是'独占'最大值.但是当Random.Next()函数的max <min时,它会抛出ArgumentOutOfRangeException.因此,微软的实施在这方面确实存在不一致和错误.

您可能只想在min> max时简单地交换数字,这样就不会引发错误,但这完全取决于所需的内容.如果你想在无效值上出错,那么当我们的代码中微软的独占最大值(max + 1)等于最小值时,最好也抛出错误,在这种情况下MS不能出错.

处理max = Int32.MaxValue有点不方便的解决办法,但我希望发布一个处理这两种情况的彻底函数.如果你想要不同于我编码的行为,请适合自己.但请注意这两个问题.

快乐的编码!

编辑:所以我需要一个随机整数生成器,我决定将它编码为"正确".因此,如果有人想要完整的功能,这里有一个实际工作.(但它只用2行代码就没有赢得最简单的奖项.但它也不是很复杂.)

''' <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
Run Code Online (Sandbox Code Playgroud)

  • 完全胡说八道。正如比尔所说,`Next()` 的行为是完全正常的,而不是“很奇怪”。 (2认同)

小智 5

Microsoft Rnd 函数示例

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

1- 初始化随机数生成器。

Randomize()
Run Code Online (Sandbox Code Playgroud)

2 - 生成 1 到 6 之间的随机值。

Dim value As Integer = CInt(Int((6 * Rnd()) + 1))
Run Code Online (Sandbox Code Playgroud)