如何仅用Random(0,1)实现Random(a,b)?

发布于 2024-12-23 16:01:59 字数 859 浏览 2 评论 0原文

可能的重复:
如何穿制服通过已知的均匀随机函数 RANDOM(0,1) 在 a, b 之间随机生成

算法导论一书中,有一个注释:

描述该过程的实现Random(a, b) 仅调用 Random(0,1)。作为 a 和 b 的函数,程序的预期运行时间是多少? Random(a,b) 结果的概率应该是纯均匀分布的,如 Random(0,1)

对于 Random 函数,结果是 a 和 b 之间的整数(含)。例如,Random(0,1) 生成 0 或 1; Random(a, b) 生成 a, a+1, a+2, ..., b

我的解决方案是这样的:

for i = 1 to b-a
    r = a + Random(0,1)
return r

运行时间是 T=ba

这是正确的吗?我的解决方案的结果是均匀分布的吗?

谢谢

如果我的新解决方案是这样的怎么办:

r = a
for i = 1 to b - a //including b-a
    r += Random(0,1)
return r

如果不正确,为什么 r += Random(0,1) 使 r 不均匀分布?

Possible Duplicate:
how to get uniformed random between a, b by a known uniformed random function RANDOM(0,1)

In the book of Introduction to algorithms, there is an excise:

Describe an implementation of the procedure Random(a, b) that only makes calls to Random(0,1). What is the expected running time of your procedure, as a function of a and b? The probability of the result of Random(a,b) should be pure uniformly distributed, as Random(0,1)

For the Random function, the results are integers between a and b, inclusively. For e.g., Random(0,1) generates either 0 or 1; Random(a, b) generates a, a+1, a+2, ..., b

My solution is like this:

for i = 1 to b-a
    r = a + Random(0,1)
return r

the running time is T=b-a

Is this correct? Are the results of my solutions uniformly distributed?

Thanks

What if my new solution is like this:

r = a
for i = 1 to b - a //including b-a
    r += Random(0,1)
return r

If it is not correct, why r += Random(0,1) makes r not uniformly distributed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

送舟行 2024-12-30 16:01:59

其他人已经解释了为什么您的解决方案不起作用。正确的解决方案如下:

1) 找到最小的数 p,使得 2^p > ba。

2) 执行以下算法:

r=0
for i = 1 to p
    r = 2*r + Random(0,1)

3) 如果 r 大于 ba,则转至步骤 2。

4) 您的结果是 r+a

那么让我们尝试随机(1,3)。
所以 ba 是 2。
2^1 = 2,因此 p 必须为 2,以便 2^p 大于 2。

所以我们将循环两次。让我们尝试所有可能的输出:

00 -> r=0, 0 is not > 2, so we output 0+1 or 1.
01 -> r=1, 1 is not > 2, so we output 1+1 or 2.
10 -> r=2, 2 is not > 2, so we output 2+1 or 3.
11 -> r=3, 3 is > 2, so we repeat.

所以 1/4 的时间,我们输出 1。我们输出 2 的时间的 1/4。我们输出 3 的时间的 1/4。我们必须重复的时间的 1/4第二次算法。看起来不错。

请注意,如果您必须经常这样做,则有两种优化方法很方便:

1)如果您经常使用相同的范围,请使用一个计算 p 一次的类,这样您就不必计算它每次。

2) 许多 CPU 有快速的方法来执行高级语言中未公开的步骤 1。例如,x86 CPU 具有 BSR 指令。

Others have explained why your solution doesn't work. Here's the correct solution:

1) Find the smallest number, p, such that 2^p > b-a.

2) Perform the following algorithm:

r=0
for i = 1 to p
    r = 2*r + Random(0,1)

3) If r is greater than b-a, go to step 2.

4) Your result is r+a

So let's try Random(1,3).
So b-a is 2.
2^1 = 2, so p will have to be 2 so that 2^p is greater than 2.

So we'll loop two times. Let's try all possible outputs:

00 -> r=0, 0 is not > 2, so we output 0+1 or 1.
01 -> r=1, 1 is not > 2, so we output 1+1 or 2.
10 -> r=2, 2 is not > 2, so we output 2+1 or 3.
11 -> r=3, 3 is > 2, so we repeat.

So 1/4 of the time, we output 1. 1/4 of the time we output 2. 1/4 of the time we output 3. And 1/4 of the time we have to repeat the algorithm a second time. Looks good.

Note that if you have to do this a lot, two optimizations are handy:

1) If you use the same range a lot, have a class that computes p once so you don't have to compute it each time.

2) Many CPUs have fast ways to perform step 1 that aren't exposed in high-level languages. For example, x86 CPUs have the BSR instruction.

做个ˇ局外人 2024-12-30 16:01:59

不,这是不正确的,该方法将集中在 (a+b)/2 周围。这是二项分布。

您确定 Random(0,1) 生成整数吗?如果它产生 0 到 1 之间的浮点值,则更有意义。那么解决方案将是仿射变换,运行时间独立于 ab

我刚刚想到的一个想法,如果它与整数值有关:使用二分法。每一步都有一个低-高范围。如果 Random(0,1) 返回 0,则下一个范围是 low-(low+high)/2,否则 (low+high)/2-高。
细节和复杂性留给你,因为这是家庭作业。

这应该会创建(大约)均匀分布。

编辑:大约是那里的重要词。如果 b-a+1 是 2 的幂,则为统一,如果接近则相差不太远,但总体来说还不够好。啊,好吧,这是一个自发的想法,无法让他们一切顺利。

No, it's not correct, that method will concentrate around (a+b)/2. It's a binomial distribution.

Are you sure that Random(0,1) produces integers? it would make more sense if it produced floating point values between 0 and 1. Then the solution would be an affine transformation, running time independent of a and b.

An idea I just had, in case it's about integer values: use bisection. At each step, you have a range low-high. If Random(0,1) returns 0, the next range is low-(low+high)/2, else (low+high)/2-high.
Details and complexity left to you, since it's homework.

That should create (approximately) a uniform distribution.

Edit: approximately is the important word there. Uniform if b-a+1 is a power of 2, not too far off if it's close, but not good enough generally. Ah, well it was a spontaneous idea, can't get them all right.

如此安好 2024-12-30 16:01:59

不,您的解决方案不正确。这个总和将服从二项式分布。

但是,您可以生成 0、1 的纯随机序列并将其视为二进制数。

repeat
  result = a
  steps = ceiling(log(b - a))

  for i = 0 to steps
    result += (2 ^ i) * Random(0, 1)
until result <= b

KennyTM:我的错。

No, your solution isn't correct. This sum'll have binomial distribution.

However, you can generate a pure random sequence of 0, 1 and treat it as a binary number.

repeat
  result = a
  steps = ceiling(log(b - a))

  for i = 0 to steps
    result += (2 ^ i) * Random(0, 1)
until result <= b

KennyTM: my bad.

人事已非 2024-12-30 16:01:59

我阅读了其他答案。为了好玩,这里有另一种查找随机数的方法:

分配一个包含 ba 元素的数组。
将所有值设置为 1
迭代数组。对于每个非零元素,就像掷硬币一样。如果出现0,则将该元素设置为0

每当完成一次迭代后,只剩下 1 个元素时,您就会得到随机数:a+i,其中 i 是非零元素的索引(假设我们开始在 0 上建立索引)。那么所有数字都有相同的可能性。 (您必须处理平局的情况,但我将其作为练习留给您。)

这将有 O(infinity) ... :)
但平均而言,一半的数字将被消除,因此它的平均案例运行时间为 log_2 (ba)

I read the other answers. For fun, here is another way to find the random number:

Allocate an array with b-a elements.
Set all the values to 1.
Iterate through the array. For each nonzero element, flip the coin, as it were. If it is came up 0, set the element to 0.

Whenever, after a complete iteration, you only have 1 element remaining, you have your random number: a+i where i is the index of the nonzero element (assuming we start indexing on 0). All numbers are then equally likely. (You would have to deal with the case where it's a tie, but I leave that as an exercise for you.)

This would have O(infinity) ... :)
On average, though, half the numbers would be eliminated, so it would have an average case running time of log_2 (b-a).

夜血缘 2024-12-30 16:01:59

首先,我假设您实际上是在累加结果,而不是在每个步骤中向 a 添加 0 或 1。
使用一些概率,您可以证明您的解决方案不是均匀分布的。结果值 r 为 (a+b)/2 的可能性最大。例如,如果 a 为 0,b 为 7,则获得值 4 的机会是(7 的组合 4)除以 2 的 7 次方。原因是,无论 7 个值中的哪 4 个,是 1,结果仍然是 4。

您估计的运行时间是正确的。

First of all I assume you are actually accumulating the result, not adding 0 or 1 to a on each step.
Using some probabilites you can prove that your solution is not uniformly distibuted. The chance that the resulting value r is (a+b)/2 is greatest. For instance if a is 0 and b is 7, the chance that you get a value 4 is (combination 4 of 7) divided by 2 raised to the power 7. The reason for that is that no matter which 4 out of the 7 values are 1 the result will still be 4.

The running time you estimate is correct.

您的好友蓝忘机已上羡 2024-12-30 16:01:59

您的解决方案的伪代码应如下所示:

r=a
for i = 0 to b-a
    r+=Random(0,1)
return r

至于均匀分布,假设该随机数生成器所基于的随机实现完全均匀,则获得 0 或 1 的几率为 50%。因此,得到你想要的号码是一次又一次选择的结果。

所以对于a=1,b=5,有5种选择。

获得 1 的几率涉及 5 个决策,全为 0,其几率为 0.5^5 = 3.125%

获得 5 的几率涉及 5 个决策,全部为 1,其几率为 0.5^5 = 3.125%

如您所见由此看来,分布并不均匀——任何数字的几率都应为 20%。

Your solution's pseudocode should look like:

r=a
for i = 0 to b-a
    r+=Random(0,1)
return r

As for uniform distribution, assuming that the random implementation this random number generator is based on is perfectly uniform the odds of getting 0 or 1 are 50%. Therefore getting the number you want is the result of that choice made over and over again.

So for a=1, b=5, there are 5 choices made.

The odds of getting 1 involves 5 decisions, all 0, the odds of that are 0.5^5 = 3.125%

The odds of getting 5 involves 5 decisions, all 1, the odds of that are 0.5^5 = 3.125%

As you can see from this, the distribution is not uniform -- the odds of any number should be 20%.

活泼老夫 2024-12-30 16:01:59

在您创建的算法中,它实际上并不是均匀分布的。

结果“r”将始终是“a”或“a+1”。它永远不会超出这个范围。

它应该看起来像这样:

r=0;
for i=0 to b-a
   r = a + r + Random(0,1)

return r;

通过在计算中包含“r”,您就包含了所有先前“for”循环运行的“随机性”。

In the algorithm you created, it is really not equally distributed.

The result "r" will always be either "a" or "a+1". It will never go beyond that.

It should look something like this:

r=0;
for i=0 to b-a
   r = a + r + Random(0,1)

return r;

By including "r" into your computation, you are including the "randomness" of all the previous "for" loop runs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文