如何基于数组加权随机数

时间:2013-01-30 12:12:05

标签: c# .net algorithm random weighted

我一直在考虑如何实施一些东西,坦率地说,这超出了我的数学技能。所以,请随时尝试指出我正确的方向,而不是完整的代码解决方案,我将不胜感激。

所以,想象一下,我已经对文本进行了分析,并生成了一个不同的两个字符组合的频率表。我将它们存储在26x26阵列中。 例如。

  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
A 1 15 (frequency of AA, then frequency of AB etc.)
B 12 0 (freq of BA, BB etc..)
... etc.

所以我想随机选择这两个字符组合,但我想根据频率“权衡”我的选择。即。上面的AB应该比AA高15倍。并且,显然,选择不应该返回类似BB的东西(即频率为0 - 在这个例子中,显然BB确实出现在像Bubble !! :-)这样的单词中)。对于0的情况,我意识到我可以循环,直到我得到一个非0频率,但这并不优雅,因为我有一种感觉/直觉,有一种方法可以扭曲我的平均值。

我在考虑选择我的第一个字符 - 即。行 - (我最终生成了4对序列)我可以使用系统随机函数(Random class.Next)然后使用'加权'随机算法来选择第二个字符。

有什么想法吗?

6 个答案:

答案 0 :(得分:5)

鉴于您的示例示例,我将首先创建所有数字的累积序列(1,15,12,0 => 1,16,28,28)。

然后我会产生一个0到27之间的随机数(比方说19)。

然后我会计算出19是> = 16但是< 28,给我3桶(BA)。

答案 1 :(得分:5)

对于您的具体问题,其他答案中有一些很好的建议。为了解决“我有一个符合统一概率分布的随机数源,但我希望它符合给定的非均匀概率分布”的一般问题,那么你可以解决< em>分位数函数,这是执行该转换的函数。我给出了一个温和的介绍,解释了为什么分位数函数是你想要的函数:

Generating Random Non-Uniform Data In C#

答案 2 :(得分:1)

如何对所有频率求和并使用从AA到ZZ的频率来生成你的对。

假设你有一个总频率的对,如果rnd返回0你获得AA如果它返回1-14然后它的AB等

答案 3 :(得分:1)

使用频率矩阵生成一组完整的值。通过Random.Next()对集合进行排序。将随机集存储在数组中。然后,如果该数组基于Random.Next(randomarray.Length),你可以选择一个元素。

如果有一种计算频率的数学方法,你也可以这样做。但是,如果重复调用此方法,则创建预编译和缓存集将减少计算时间。

请注意,根据最大频率,这可能需要大量存储空间。在循环构建集合之前,您还需要创建随机实例。这样你就不会重新设置随机生成器了。

...

另一种方式(类似于你在问题末尾的建议)将在两次传递中执行此操作,第一次选择行,第二种使用加权频率选择列。这只是在一个范围内限制的行频率的总和。第一个建议应该根据重量给出更均匀的分布。

答案 4 :(得分:0)

取概率之和。取零和该总和之间的随机数。将概率相加,直到得到概率大于或等于随机数。然后使用你的项目。

例如伪代码:

b = getProbabilites()
s = sum(b)
r = randomInt() % s
i = 0
acc = 0
while (acc < r) {
    acc += b[i]
    i++
}

return i

答案 5 :(得分:0)

如果效率不是问题,您可以创建key-&gt;值哈希而不是数组。这样做的好处是(如果你在文本中很好地格式化),如果需要,更新值将非常容易。像

这样的东西
{
    AA => 5, AB => 2, AC => 4,
    BA => 6, BB => 5, BC => 9,
    CA => 2, CB => 7, CC => 8
}

通过这种方式,您可以轻松检索所需序列的值,并快速找到要更新的条目。如果表是自动生成的并且非常大,那么可以帮助熟悉vim对正则表达式的使用。