VB.NET의 임의 정수
단위 검정에 사용하려면 1과 n 사이의 임의 정수(여기서 n은 양의 정수)를 생성해야 합니다.저는 진정한 무작위성을 보장하기 위해 지나치게 복잡한 것이 필요하지 않습니다. 단지 구식 무작위 숫자일 뿐입니다.
내가 그걸 어떻게 하겠어요?
여러 번 지적되었듯이 코드를 이렇게 작성하자는 제안은 문제가 있습니다.
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
그 이유는 다음을 위한 생성자이기 때문입니다.Randomclass를 합니다.대부분의 시스템에서 이는 제한적인 세분성을 가집니다(약 20ms).따라서 다음 코드를 작성하면 동일한 번호가 여러 번 연속으로 표시됩니다.
Dim randoms(1000) As Integer
For i As Integer = 0 to randoms.Length - 1
randoms(i) = GetRandom(1, 100)
Next
다음 코드는 이 문제를 해결합니다.
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
저는 두 가지 방법을 사용하여 1에서 100 사이의 25개의 무작위 정수를 생성하는 간단한 프로그램을 만들었습니다.다음은 출력입니다.
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
1과 N(포함) 사이의 임의 정수 값을 얻으려면 다음을 사용합니다.
CInt(Math.Ceiling(Rnd() * n)) + 1
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)
Microsoft 예제 Rnd 함수
https://msdn.microsoft.com/en-us/library/f7s023d2%28v=vs.90%29.aspx
1 - 난수 발생기를 초기화합니다.
Randomize()
2 - 1에서 6 사이의 랜덤 값을 생성합니다.
Dim value As Integer = CInt(Int((6 * Rnd()) + 1))
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
지금까지 나온 모든 답에는 문제나 버그(하나가 아니라 여러 개)가 있습니다.설명해 드리겠습니다.하지만 먼저 정적 변수를 사용하여 생성기 변수를 기억하는 댄 타오의 통찰력을 칭찬하고 싶습니다. 그러면 생성기 변수를 여러 번 호출하면 같은 #이 반복되지 않을 것입니다. 게다가 그는 매우 멋진 설명을 해주었습니다.하지만 그의 코드는 제가 지금 설명하는 것처럼 대부분의 다른 사람들이 가지고 있는 것과 같은 결함을 겪었습니다.
MS는 Next() 메서드를 다소 특이하게 만들었습니다.Min 매개 변수는 예상한 대로 포함 최소값이지만 Max 매개 변수는 예상하지 못한 대로 배타적 최대값입니다.즉, min=1 및 max=5를 통과하면 난수는 1, 2, 3 또는 4가 되지만 5는 포함되지 않습니다.이것은 마이크로소프트의 랜덤을 사용하는 모든 코드의 두 가지 잠재적 버그 중 첫 번째입니다.다음() 메서드입니다.
간단한 답변(다른 가능성은 있지만 드문 문제도 있음)을 위해서는 다음을 사용해야 합니다.
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
(나는 사용하기를 좋아합니다.Int32Integer왜냐하면 그것은 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.일 때는 '전용' max가 아니라 random에 대해 max < min.일 때는 정말로 max가 됩니다.다음() 함수는 Argument Out Of Range Exception을 던집니다.따라서 마이크로소프트의 구현은 이 점에서도 일관성이 없고 버그가 많습니다.
오류가 발생하지 않도록 min > max 때 단순히 숫자를 교환하고 싶을 수도 있지만, 그것은 전적으로 원하는 것에 달려 있습니다.잘못된 값에 오류가 발생하기를 원한다면 Microsoft 코드의 배타적 최대값(최대 + 1)이 최소값과 같을 때 오류를 발생시키는 것이 좋습니다. 이 경우 MS가 오류를 발생시키지 못합니다.
max = Int32일 때의 해결 방법을 처리합니다.MaxValue는 조금 불편하지만, 저는 이 두 가지 상황을 모두 처리하는 철저한 기능을 게시할 것으로 예상합니다.제가 코딩한 것과 다른 행동을 원한다면 마음대로 하세요.하지만 이 두 가지 문제를 알고 있어야 합니다.
해피 코딩!
편집: 그래서 저는 무작위 정수 생성기가 필요했고, 그것을 '옳게' 코딩하기로 결정했습니다.그래서 만약 누군가가 완전한 기능을 원한다면, 실제로 작동하는 것이 있습니다. (하지만 코드 두 줄만으로 가장 간단한 상을 받는 것은 아닙니다.)하지만 실제로 복잡하지도 않습니다.)
''' <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
의사 난수 생성기는 다음과 같이 한 번만 생성해야 합니다.
Dim Generator As System.Random = New System.Random()
그런 다음 정수가 필요한 경우 다음을 사용할 수 있습니다.
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
몇 번이라도.래퍼 함수를 사용하는 것은 최대값이 배타적이기 때문에 정당화됩니다. 저는 난수가 이러한 방식으로 작동한다는 것을 알고 있지만 의 정의입니다.다음은 헷갈립니다.
번호가 필요할 때마다 생성기를 생성하는 것은 잘못된 것이라고 생각합니다. 의사 난수는 이러한 방식으로 작동하지 않습니다.
먼저, 다른 답변에서 논의된 초기화 문제가 발생합니다.한 번 초기화하면 이 문제가 발생하지 않습니다.
둘째, 저는 여러분이 임의의 숫자의 유효한 시퀀스를 얻을 수 있는지 전혀 확신할 수 없습니다. 오히려, 여러분은 컴퓨터 시간을 기반으로 자동으로 시드되는 여러 개의 서로 다른 시퀀스의 첫 번째 수를 얻게 됩니다.저는 이 숫자들이 시퀀스의 무작위성을 확인하는 테스트를 통과할지 확신할 수 없습니다.
당신이 요셉의 대답을 사용하고 있다면, 그것은 훌륭한 대답이고, 당신은 이것들을 다음과 같이 연속적으로 실행합니다.
dim i = GetRandom(1, 1715)
dim o = GetRandom(1, 1715)
그러면 통화를 너무 빨리 처리하기 때문에 결과가 반복적으로 동일하게 나타날 수 있습니다.2008년에는 이 문제가 발생하지 않았을 수도 있지만, 현재 프로세서 속도가 훨씬 빠르기 때문에 이 기능은 두 번째 통화를 하기 전에 시스템 클럭을 변경할 수 있는 충분한 시간을 허용하지 않습니다.
시스템 이후로.랜덤() 기능은 시스템 클럭을 기반으로 하므로 다음 통화 전에 변경할 수 있는 충분한 시간이 필요합니다.이를 수행하는 한 가지 방법은 현재 스레드를 1밀리초 동안 일시 중지하는 것입니다.아래 예를 참조하십시오.
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
Dim rnd As Random = New Random
rnd.Next(n)
참고로, RND와 RANDOMIZE에 대한 VBNET Function 정의(기본(1980년) 이후의 모든 버전은 동일한 결과를 제공해야 함)는 다음과 같습니다.
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
랜덤 CLASS는 다음과 같습니다.
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
사용에 만족하지 않는 사용자의 답변을 많이 봅니다.System.Random.
개인적으로 여전히 사용할 것임에도 불구하고System.Random저는 GUID를 랜덤 값의 기준으로 사용하는 방법에 대해 생각하고 있었습니다.GUID는 다음을 사용하여 바이트 배열로 변환할 수 있습니다.ToByteArray방법, 그리고 결과 바이트 배열은 다음을 사용하여 숫자 값으로 변환될 수 있습니다.BitConverter.
'Function for reuse (min is inclusive and max is exclusive)
Function GetRandom(min As Integer, max As Integer) As Integer
Return BitConverter.ToUInt64(Guid.NewGuid.ToByteArray) Mod (max - min) + min
End Function
'one-liner specific for your purpose (n is exclusive)
BitConverter.ToUInt64(Guid.NewGuid.ToByteArray) Mod (n - 1) + 1
이것은 단지 작은 사고 실험일 뿐입니다.저는 성능을 테스트하지도 않았고, 결과의 실제 "무작위성"을 조사하지도 않았습니다.하지만 당신의 목적을 위해서라면, 그것은 그저 효과가 있을 것입니다.
승인된 답변은 방법을 사용하는데, 이것은 정말 간단하고 매력적인 한 줄기를 제공하지만, 저는 개인적으로 다음을 사용하는 새로운 코드를 쓰는 것을 피합니다.Microsoft.VisualBasic네임스페이스입니다.
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]이것이 처음부터 시작하는 최선의 방법입니다.p
언급URL : https://stackoverflow.com/questions/18676/random-integer-in-vb-net
'programing' 카테고리의 다른 글
| Objective-C의 클래스 이름의 NSString에서 개체 생성 (0) | 2023.06.22 |
|---|---|
| Vuex 스토어에서 Vue.js 자동 해제 경고 (0) | 2023.06.22 |
| Cell OpenPyX에 배경색 추가l (0) | 2023.06.17 |
| 최고의 OAuth2 C# 라이브러리는 무엇입니까? (0) | 2023.06.17 |
| 링크에서 파란색 밑줄 제거 (0) | 2023.06.17 |