生成排序的随机整数而没有排序?上)

时间:2009-12-08 10:19:17

标签: math sorting random

刚刚查看有关generating a sorted list of 100 random integers的代码高尔夫问题。然而,突然出现的是,您可以生成一个正增量列表,并将它们添加到运行总计中,这样就可以了:

deltas: 1 3 2  7  2
ints:   1 4 6 13 15

事实上,你会使用浮点数,然后标准化以适应某些上限,然后舍入,但效果是一样的。

虽然不会缩短代码,但如果没有排序步骤肯定会更快。但我没有真正处理的是:整数分布是否与从均匀分布的概率密度函数生成100个随机整数相同?

编辑:示例脚本:

import random,sys
running = 0
max = 1000
deltas = [random.random() for i in range(0,11)]
floats = []
for d in deltas:
    running += d
    floats.append(running)
upper = floats.pop()
ints = [int(round(f/upper*max)) for f in floats]
print(ints)

谁的输出(公平骰子滚动)是:

[24, 71, 133, 261, 308, 347, 499, 543, 722, 852]

更新: Alok's answerDan Dyer's comment指出使用exponential distribution进行增量会得到均匀的整数分布。

8 个答案:

答案 0 :(得分:18)

所以你要问的是,以这种方式生成的数字是否会均匀分布。

您正在制作一个系列:

y j i = 0 j (x i / A)

其中A是所有x i 的总和。 x i 是(正)增量的列表。

如果x i 呈指数分布(具有任何固定均值),则可以这样做。因此,如果x i 均匀分布,则得到的y j 将不会均匀分布。

话虽如此,生成指数x i 值相当容易。

一个例子是:

sum := 0
for I = 1 to N do:
    X[I] = sum = sum - ln(RAND)
sum = sum - ln(RAND)
for I = 1 to N do:
    X[I] = X[I]/sum

您将随机数字排在[0, 1)范围内。

参考:Generating Sorted Lists of Random Numbers。本文还有其他(更快)的算法。

当然,这会产生浮点数。对于整数的均匀分布,您可以在最后一步中将sum替换为sum/RANGE(即RHS变为X[I]*RANGE/sum,然后将数字四舍五入到最接近的整数)。

答案 1 :(得分:5)

uniform distribution有一个上限和下限。如果您使用您提出的方法,并且您的增量恰好被选择得足够大,以至于在生成所有数字之前遇到上限,那么您的算法接下来会做什么?

话虽如此,您可能需要调查Poisson distribution,这是在给定平均频率下发生的随机事件之间的间隔时间分布。

答案 2 :(得分:4)

如果您将数字范围设置为1到1000,并且必须使用其中的100个数字,则delta必须至少为10,否则您将无法达到1000标记。有些人正在努力证明它在行动......

均匀分布随机选择中任何给定数字的概率为100/1000,例如1/10 - 没有震惊,以此为基础。

假设你开始使用delta并且delta只有10。

获得数字1的几率是1/10 - 看起来很好。 获得数字2的几率是1/10 +(1/10 * 1/10)(因为你可以连续命中2个增量1,或者只是命中2作为第一个增量。) 获得数字3的几率是1/10 +(1/10 * 1/10 * 1/10)+(1/10 * 1/10)+(1/10 * 1/10)

第一种情况是3的增量,第二种情况是连续3次增加3次增量,第三种情况是1的增量后跟2,第4种情况是2的增量后跟1 1。

为了我的手指打字,我们不会生成达到5的组合。

前几个数字的直接随机数比例更高。

这可以通过改变delta值来改变,因此分数都是不同的,但我不相信你能找到产生相同赔率的delta。

要给出一个可能只是沉沦它的类比,如果你认为你的delta只有6而你运行两次就相当于投掷2个骰子 - 每个增量都是独立的,但你知道7有更高的被选中的机会比2。

答案 3 :(得分:2)

我认为它会非常相似,但由于规范化,极端情况会有所不同。例如,在1到100之间随机选择的100个数字都可以是1.但是,使用您的系统创建的100个数字都可以具有0.01的增量,但是当您将它们标准化时,您将它们扩展到1 - >范围内;这意味着你永远不会得到一组非常低数字的奇怪可能性。

答案 4 :(得分:2)

Alok's answerDan Dyer's comment指出使用exponential distribution进行增量可以得到均匀的整数分布。

所以问题中代码示例的新版本将是:

import random,sys
running = 0
max = 1000
deltas = [random.expovariate(1.0) for i in range(0,11)]
floats = []
for d in deltas:
    running += d
    floats.append(running)
upper = floats.pop()
ints = [int(round(f/upper*max)) for f in floats]
print(ints)

请注意使用random.expovariate(1.0)Python exponential distribution random number generator(非常有用!)。在这里,它的平均值为1.0,但由于脚本与序列中的最后一个数字进行归一化,因此平均值本身并不重要。

输出(公平骰子滚动):

[11, 43, 148, 212, 249, 458, 539, 725, 779, 871]

答案 5 :(得分:1)

问:结果的整数分布是否与从均匀分布的概率密度函数生成100个随机整数相同?

答:每个delta都是均匀分布的。中心极限定理告诉我们,大量此类偏差之和的分布(因为它们具有有限的均值和方差)将倾向于正态分布。因此,序列中的后续偏差将 not 均匀分布。

所以简短的回答是“不”。我不能在不做代数的情况下提供一个简单的解决方案我今天没时间做!

答案 6 :(得分:1)

reference中的Alok's answer(1979)很有意思。它给出了一种算法,用于生成统一的顺序统计,而不是通过加法,而是通过连续乘法:

max = 1.
for i = N downto 1 do
   out[i] = max = max * RAND^(1/i)

其中RAND在[0,1)上是均匀的。这样你不必在最后进行标准化,实际上甚至不必将数字存储在数组中;你可以用它作为迭代器。

The Exponential distribution: theory, methods and applications By N. Balakrishnan, Asit P. Basu在第22页给出了该算法的另一个推导,并归功于Malmquist(1950)。

答案 7 :(得分:0)

你可以两次通过;

在第一遍中,生成0和(MAX_RAND / n)之间的增量

在第二遍中,将随机数标准化为界限

仍为O(n),具有良好的参考位置。