2013-01-08 75 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) 
     } 
}