总结篇:面试中 随机数"等概率"vs"不等概率"生成问题

转载:http://www.cnblogs.com/hellogiser/p/random-generator-with-equal-or-unequal-probability.html

1. 等概率生成

(1) rand5生成rand3

现在有一个Rand5函数,可以生成等概率的[0, 5)范围内的随机整数,要求利用此函数写一个Rand3函数(除此之外,不能再使用任何能产生随机数的函数或数据源),生成等概率的[0, 3)范围内的随机整数。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand5 to generate rand3
int  Rand3()
{
    
int  x;
    
do
    {
        x = Rand5();
    }
    
while  (x >=  3 );
    
return  x;
}
(2) rand3生成rand5
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand3 to generate rand5
int  Rand5()
{
    
int  x;
    
do
    {
        x = Rand3() * 
3  + Rand3();
    }
    
while  (x >=  5 );
    
return  x;
}
(3) rand5生成rand7
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand5 to generate rand7
int  Rand7()
{
    
int  x;
    
do
    {
        x = Rand5() * 
5  + Rand5();
    }
    
while  (x >=  21 );
    
return  x %  7 ;
}
(4) rand7生成rand10
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand7 to generate rand10
int  Rand10()
{
    
int  x;
    
do
    {
        x = Rand7() * 
7  + Rand7();
    }
    
while  (x >=  40 );
    
return  x %  10 ;
}
(5) rand_m生成rand_n

 归纳总结:将这个问题进一步抽象,已知random_m()随机数生成器的范围是[0, m) 求random_n()生成[0, n)范围的函数,m < n && n <= m *m。

设t为n的最大倍数,且满足t<m*m,即 t = ((m*m)/n)*n;

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

// use rand_m to generate rand_n
int  Rand_n()
{
    
int  x;
    
do
    {
        t = ((m * m) / n) * n;
        x = Rand_m() * m + Rand_m ();
    }
    
while  (x >= t);
    
return  x % n;
}

2. 不等概率生成

(1) 如何产生如下概率的随机数?0出1次,1出现2次,2出现3次,n-1出现n次?
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  random( int  size)
{
    
while ( 1 )
    {
        
int  m = rand(size);
        
int  n = rand(size);
        
if (m + n < size)
            
return  m + n;
    }
}
(2) rand以不等概率生成01, 如何以1/n的等概率产生1~n之间的任意一个数?

已知随机函数rand(),以p的概率产生0,以1-p的概率产生1,现在要求设计一个新的随机函数newRand(),使其以1/n的等概率产生1~n之间的任意一个数。

解决思路:

可以通过已知随机函数rand()产生等概率产生0和1的新随机函数Rand(),然后调用k(k为整数n的二进制表示的位数)次Rand()函数,得到一个长度为k的0和1序列,以此序列所形成的整数即为1--n之间的数字。

注意:从产生序列得到的整数有可能大于n,如果大于n的话,则重新产生直至得到的整数不大于n。

第一步:由rand()函数产生Rand()函数,Rand()函数等概率产生0和1。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  Rand()
{
    
while ( 1 )
    {
        
int  i1 = rand();
        
int  i2 = rand();
        
if (i1 ==  0  && i2 ==  1 )
            
return   1 ;
        
else   if (i1 ==  1  && i2 ==  0 )
            
return   0 ;
    }
}

第二步:计算整数n的二进制表示所拥有的位数k,k = 1 +log2n(log以2为底n)

第三步:调用k次Rand()产生随机数,产生的k个01序列表示1-n之间的数。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/3
*/

int  newRand()
{
    
while ( 1 )
    {
        
int  result =  0 ;
        
for ( int  i =  0  ; i < k ; ++i)
        {
            
if (Rand() ==  1 )
                result |= (
1  << i);
        }
        
if (result <= n)
            
return  result;
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法`generate()`是C++ STL的一个算法函数,它可以用于生成序列。其,第一个参数是要生成序列的容器的起始迭代器,第二个参数是要生成序列的容器的结束迭代器,第三个参数是用于生成序列的函数或随机数生成器。 下面分别介绍如何使用`generate()`函数生成随机数生成斐波那契数列。 1. 生成随机数 使用`std::generate()`函数和C++11随机数引擎`std::default_random_engine`可以生成指定范围内的随机数序列。例如,生成10个在[0, 100]之间的随机数,可以这样实现: ```c++ #include <iostream> #include <algorithm> #include <vector> #include <random> int main() { std::vector<int> v(10); std::default_random_engine e; // 默认的随机数引擎 std::uniform_int_distribution<int> u(0, 100); // 生成[0, 100]之间的随机整数 std::generate(v.begin(), v.end(), [&]{ return u(e); }); // 用generate函数生成随机数序列 for (auto x : v) std::cout << x << " "; std::cout << std::endl; return 0; } ``` 2. 生成斐波那契数列 使用`std::generate()`函数和lambda表达式可以生成斐波那契数列。例如,生成前20个斐波那契数列,可以这样实现: ```c++ #include <iostream> #include <algorithm> #include <vector> int main() { std::vector<int> v(20); int a = 0, b = 1; std::generate(v.begin(), v.end(), [&]{ int c = a + b; a = b; b = c; return a; }); // 用generate函数生成斐波那契数列 for (auto x : v) std::cout << x << " "; std::cout << std::endl; return 0; } ``` 以上就是使用`generate()`函数生成随机数生成斐波那契数列的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值