2013-01-08 74 views
2

我需要創建一個方法,該方法返回某個隨機分佈的採樣數字,每次調用該方法返回的數字都比以前返回的數字大。巨大的隨機數排序列表

或換句話說,我需要一個隨機值排序列表的迭代器。

不幸的是,這個列表太大而無法在整個內存中創建。我想出的第一個想法是將我的價值空間分成桶,其中每個桶包含某些範圍[a,b)的值。 說我的清單有N個元素。要創建一個桶,我會對我的分佈進行N次抽樣,並將每個值放入[a,b)範圍內。該桶外的值將被丟棄。

這樣我就可以創建一個新的存儲桶,每次我重複上一次並保持內存消耗低。

但是,由於我不是統計專家,我有點害怕這會使我得到的數字變得糟糕。這是一個合適的方法嗎?每個存儲桶使用相同的確切分佈生成器(org.apache.commons.math3.distribution.RealDistribution的實例)是否很重要?

更新:看來我做了一個糟糕的工作來解釋我在說什麼樣的隨機數。

我的數字形成隨機分佈的樣本,例如平均值爲m且方差爲v的正態分佈,或者均勻分佈或指數分佈。

我使用這些數字來模擬仿真中的某些行爲。假設我想在某些時候觸發事件。我需要安排數十億次事件,這些事件觸發的次數必須形成一個隨機分佈的樣本。

所以,如果我通過添加一個隨機數到我以前的數字來得到我的下一個數字,我確實得到了一個增長的隨機數序列,但數字不會形成我的分佈樣本。

+0

你所要求的是什麼,絕對不是小事。我期望該程序在存在時必須使用將非常依賴於您從中抽取的分佈。 – Lucas

+0

請參閱下面的解決方案。這完全取決於在裝箱時使用固定種子可以多次創建同一份分配樣品的要求。 –

回答

0

您可以添加一個隨機數到先前生成的數字。所以你必須只保留在迭代步驟中生成的數字。

1

如果列表太大而無法存儲在內存中,則可以使用數據庫並讀取/寫入數據庫批量的列表項。

這樣你只需要在任何時候在內存中存儲一​​個批處理。

+0

是否有數據結構可以有效處理這個問題? – Lucas

3

你可以說什麼是你的隨機發生器的要求。

我需要創建一個方法,該方法返回某個隨機分佈的採樣數字,每次調用該方法返回的數字都比以前返回的數字大。

你可以做類似的事情。

private long previous = 0; 
private final Random rand = new Random(); 

public long nextNumber() { 
    return previous += rand.nextInt(10) + 1; 
} 

具體取決於您想如何建模隨機數。

+0

好主意,但nextNumber(產生的數字)不會形成我的分佈的樣本。查看我的更新以獲得澄清。 –

+0

我懷疑你只需要時間差異是一個截斷的正態分佈。完整的正態分佈從負無窮到正無窮。在實際系統中的延誤不符合正態分佈或類似的東西(這使標準偏差而無意義;) –

+0

我需要的是一些分配;-)的有限樣本。我模擬用戶請求,例如,正態分佈可以用來模擬特定事件的行爲。 –

1

我就開始通過創建一個變量和存儲您的第一個隨機數,然後生成另一個隨機數,對它們進行比較,如果它是在這兩個大的存儲和RAM越大保存,重複的下一個隨機數會比較記憶中的單個值。

0

SamplePartitioner是一個類,它將一些分佈的樣本分成幾個固定大小的分區,它們被nextPartition()一個接一個地返回。

nextPartition()在每次調用時創建整個樣本,但只存儲最大的partitionSize值,這些值大於最後一個分區的最大值。通過使用固定的種子,每次調用它時,nextPartition()會創建完全相同的樣本。

class SamplePartitioner(sampleSize: Long, partitionSize: Int, dist: RealDistribution) { 
    private val seed = Random.nextInt 
    private var remaining = sampleSize 
    private var lastMax = 0.0 

    def nextPartition(): SortedSet[Double] = remaining.min(partitionSize) match { 
     case 0 => SortedSet.empty[Double] 
     case targetSize => 
      dist.reseedRandomGenerator(seed) 
      val partition = fill(sampleSize, SortedSet.empty, targetSize) 
      lastMax = partition.last 
      remaining -= partition.size 
      partition 
    } 

    private def fill(samples: Long, partition: SortedSet[Double], targetSize: Long): SortedSet[Double] = 
     samples match { 
      case 0 => partition 
      case n => 
       val sample = dist.sample() 
       val tmp = if (sample > lastMax) partition + sample else partition 
       fill(n - 1, if (partition.size > targetSize) tmp.init else tmp, targetSize) 
     } 
}