| |||
| 楼上貌似都理解错题意了 貌似是算法导论的习题,就是已经有一个均匀分布的int rand_5() 要实现一个int rand(n) 我改一下题目,假设rand_5返回0~4,需要构造一个0~n-1的随机数 我的方法是用k次rand_5()(5^k >= n)得到一个k位的5进制数,当这个数大于等于n时丢弃重新来一次,小于等于n时返回 例如n = 31,则k = 3,那么这个3位5进制数为rand_5() * 25 + rand_5() * 5 + rand_5() |
| |||
| 引用:
设已知Random(0, N) 要求Random(0, M) M > N 假入N=4, M=5, 那么必须至少要生成0~24个随机数才够用,也就是5*Random(0, 4) + Random(0, 4),但是大于M的直接抛弃又太浪费,于是想到可以mod M+1,但是这样又不均匀。在这种情况下,mod M+1可以如下所示: 0 ~ 5 6 ~ 11 12 ~ 17 18 ~ 23 24 事实上,如果只有位于0 ~ 23之间随机数就正好分为4组,很均匀。这里唯余一个24,mod M+1 = 0,概率空间会多一个0。 所以这里还是可以采用抛弃的思路,但是却是抛弃24的这种情况。一般来说,我们需要抛弃不能整除M+1的那一部分。算法如下: PHP 代码: 也就是说,如果直接抛弃重来,那么我们又要从0开始获取随机数,而这里可以看出,我们已经有了位于 0 ~ K 之间的均匀随机数,那么如果直接继续迭代一次, 0 -> 0* (N+1) + Random(0, N) -> 0 ~ N 1 -> ... -> N+1 ~ 2N+1 2-> ... -> 2N+2 ~ 3N+2 ... K-> ... -> KN+K ~ KN+N+K 就得到了 0 ~ KN+N+K 之间的均匀随机数,无疑加快了速度。 这个算法的本质就是利用Random(0, N)迭代产生 0 ~ N^X-1 之间的随机数,如果space够用了就mod得到所需的随机数,排除不均匀的那部分,再利用那部分继续产生随机数。如此往复。本质上和直接抛弃是一样的,不过速度要快一些。 PS:算法不是我的,网上抄的,只有分析是自己的,有点罗嗦..... ![]() 完整的算法是: PHP 代码: 此帖于 2008-04-05 02:13 AM 被 haohaolee 编辑. |
| ||||
| 引用:
|