2016-08-15 6 views
0

私のプロジェクトは非理想気体の動きを予測することですので、すべての分子に特定の数を与えるためにこのコードを書いていますが、繰り返し番号を保持しています(私はrandbetweenを使用しています) それは、同じ番号を繰り返しますか?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 

End Subの

答えて

0

åìåú私はそのように生成されている乱数を追跡するために辞書を使用してお勧めします遠い数字が辞書に存在しない場合、シミュレーションを続行できます。そうでなければ、新しい乱数を生成できます(これはElse条件になります)。

辞書を使用すると、キーはハッシュされます。

ここでは、辞書の操作方法のコードサンプルを示します。

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

ライアンで見つけることができますその部分。私は、この問題の解決策を更新しました。これは、dupを除外するためのアプローチと、その範囲のすべての数値が生成されるまで実行します。 'Remove'を使うよりもまだ高速です。パフォーマンスを比較するために、私はGitHub Gistにリンクしました。結果はソースファイルの一番下にあります。見てみましょう! :-) –

+0

@LoganReed。たぶん私は問題を誤解しているかもしれませんが、範囲内のすべての乱数を列挙すると、OPが1〜10,000でないと言います。私は必要なのは、N個のシミュレーションに基づいて乱数を繰り返さないということです。リピートしたくない場合は、For i = 1〜10000ループなどのようにするのはなぜですか? –

+0

あなたは正しいです - 私はおそらくそれを思っています。 OPは明確にする必要があります。 –

0

範囲内のすべての数値が生成されるまでの数値の生成。アルゴリズムの最後ほど非効率的です。ほとんどの乱数は「ミス」になりますが、以下のコレクションのremoveメソッドよりも効率的です。

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秒で完了しました。私はコレクションデータ構造のremoveメソッドと関係があると考えています。私は辞書データ構造を使った方が、あなたが投稿したメソッドがかなり高速になると確信しています。 –

+0

@RyanWildryハ - 非常に予期しない。 'Collection'の' Remove'メソッドのように見えるのは非常に非効率的です(おそらく、コレクション全体を上書きコピーする)。私は、あなたのメソッドは多くの悪いことを実行する価値の数が多いと思った - あまりにも多くのミスがあるため。しかし、多くのランダムなミスがまだCollection.Removeよりも "安い"ように見えます。私はそれについて考えてみましょう... –