2016-08-15 45 views
0

我的項目是預測非理想的氣體運動,所以我寫了這個代碼給每個分子一個特定的數字,但它保持重複的數字(我用蘭德之間) 我如何改變它,所以它不會重複相同的號碼?VBA中的氣體行爲

子Rand_Number() 「AACO 20àçåæUIîñôøé艾艾÷åìåú

Dim RandNum As Long 
Dim k As Long 
Dim Mone As Integer 

Mone = 0 
Num_molecules = Sheets("Data").Range("A14").Value 
RandNum = WorksheetFunction.RandBetween(1, Num_molecules) 

For j = 1 To Num_molecules * 0.2 

    If IsEmpty(Sheets("rand").Cells(1, 1)) = True Then 
      Sheets("rand").Cells(1, 1) = RandNum 

    Else 

    i = 1 
    'RandNum = WorksheetFunction.RandBetween(1, Num_molecules) 
      Do 'Until IsEmpty(Sheets("rand").Cells(i, 1)) = True 

      If Sheets("rand").Cells(i, 1) = RandNum Then 
      RandNum = WorksheetFunction.RandBetween(1, Num_molecules) 

      Do Until RandNum = Cells(i, 1) Or IsEmpty(Cells(i, 1)) = True 
       If RandNum = Sheets("rand").Cells(i, 1) Then 
        RandNum = WorksheetFunction.RandBetween(1, Num_molecules) 
       Else 
       i = i + 1 

       End If 
      Loop 


      ElseIf IsEmpty(Sheets("rand").Cells(i, 1)) = False Then 
      i = i + 1 

      Else 
      Sheets("rand").Cells(i, 1) = RandNum 

      Exit Do 

      End If 

     Loop 
    End If 


Next j 

末次

回答

0

我推薦使用字典來跟蹤那些已經產生這樣的隨機數的遠。如果字典中不存在該數字,則可以繼續進行模擬,否則可以生成一個新的隨機數(這將成爲其他條件)

使用字典對查找操作非常快速,因爲密鑰被散列。

下面是如何使用字典的代碼示例。

Public Sub DictionaryExample() 
    Dim myDict   As Object: Set myDict = CreateObject("Scripting.Dictionary") 
    Dim myRand   As Long 
    Dim i    As Long 

    For i = 1 To 10000 
     myRand = WorksheetFunction.RandBetween(1, 10000) 
     If myDict.exists(myRand) = False Then ' The random number doesn't exist in the previous items added 
               'If it doesn't exist, add it to the dictionary 
      myDict.Add myRand, myRand 'First parameter is the key, or the unique value 
             'The second parameter is the value associated with the key, the lookup value 
     Else 
      'Do something here when it does exist 
     End If 
    Next i 
End Sub 
+0

萊恩發現 - 這個實現更快,因爲它不會產生從範圍內的所有唯一的號碼,但只有一個它的一部分。我已經更新了我對這個問題的回答,這個問題同時使用了你的方法來除掉dups,並且這樣做直到生成了範圍內的所有數字。它比使用'Remove'更快。我已經將GitHub Gist與所有三者進行了比較,以比較性能。結果在源文件的底部。看一看! :-) –

+0

@LoganReed。也許我誤解了這個問題,但列舉範圍在1-10,000之間的所有隨機數並不是OP所追求的。我認爲需要的是不要重複基於N次模擬的隨機數。如果我們不想重複,爲什麼不做一個For I = 1到10000的循環,或者類似的東西? –

+0

你說得對 - 我可能會推翻它。 OP需要澄清。 –

0

生成數字,直到生成範圍內的所有數字。當算法結束時,大多數隨機數字變成「未命中」,但效率低下,但仍比下面的集合刪除方法更有效。

Sub uniqRndMissedHits() 

    Dim lb As Long: lb = 1 ' lower bound 
    Dim ub As Long: ub = 1000 ' upper bound 

    ' populate collection with numbers starting from lb to ub 
    Dim i As Long 
    Dim c As New Collection 

    ' iterate while we haven't generated all the random numbers 
    ' in the specified range 
    While c.Count < ub - lb + 1 
     i = Int((ub - lb + 1) * Rnd + lb) 
     If Not contains(c, CStr(i)) Then 
      c.Add i, CStr(i) 
      Debug.Print i ' this is your unique random number from the 
          ' remaining in the collection 
     End If 
    Wend 

End Sub 

Function contains(col As Collection, key As String) As Boolean 
    On Error Resume Next 
    col.Item key 
    contains = (Err.Number = 0) 
    On Error GoTo 0 
End Function 

此示例產生保證唯一的(即先前未產生)值,但CollectionRemove方法使得低效大量模擬。的這個回答所有的方法表現

Sub uniqRnd() 

    Dim lb As Long: lb = 1 ' lower bound 
    Dim ub As Long: ub = 1000 ' upper bound 

    ' populate collection with numbers starting from lb to ub 
    Dim i As Long 
    Dim c As New Collection 
    For i = lb To ub: c.Add i: Next 

    ' randomly pick the number and (!) remove it from the 
    ' collection at the same time so it won't be repeated 
    While c.Count > 0 
     lb = 1 
     ub = c.Count 
     i = Int((ub - lb + 1) * Rnd + lb) 
     Debug.Print c(i) ' this is your unique random number from the 
         ' remaining in the collection 
     c.Remove i 
    Wend 

End Sub 

比較可以在此GitHub的要點Excel VBA: Generate complete set of unique random numbers

+0

有趣的方法,我喜歡這個主意!我在ub = 100000的代碼中描述了你的代碼,因爲我懷疑大量的迭代可能會很慢。大約需要20秒才能執行。使用我發佈的字典方法在2秒內完成。我懷疑它與收集數據結構的刪除方法有關。我敢打賭,如果您使用字典數據結構,您發佈的方法會更快。 –

+0

@RyanWildry Ha - 非常意外。看起來'Collection'的'Remove'方法效率非常低(可能會將整個集合複製過來)。我認爲在大量的價值觀上你的方法會表現得更差 - 因爲會有太多的失誤。但它看起來像很多隨機錯過仍然比「收集。移除」更便宜。讓我想想... –