对于rand_m 生成1到n的问题

本文深入探讨了如何利用已有的rand7()函数,通过数学公式与逻辑处理,构建出能够随机产生1到10之间整数的rand10()函数。详细解释了生成等概率数集的原理,并提供了三种实现方法,包括等概率生成1到49的通用策略,以及针对特定范围的优化技巧。文章旨在为编程爱好者提供一种有趣且实用的随机数生成解决方案。

今天在网上看到了在网上传的面试题,题目是:

已知有个rand7()的函数,它可以返回1到7之间的随机自然数,现在请让利用这个rand7()来构造rand10()使它能 随机地产生1~10之间的自然数。

参考以下网址,我觉得写的不错。好像这是道编程之美上的题?

http://www.towork.me/questions/451/

 

对于这一类题目的一般公式是: m*(rand_m()-1)+rand_m();n<m && n<=m*m

注: rand_m() 可以生成 [1,m]的自然数, 要生成 rand_n() 即[1,n]的自然数的公式。

其实,这个问题,其实就是,我先生成等间距的一段数(间距一定是m),这个数分别为 0, m, 2m, 3m,..., (m-1)*m, m*m。 在 rand_m()中进行-1, 就是能够产生0。注意这个间距相当于是等概率产生的,那么,我在先定了一个起点,在这个起点的基础上,再加上一个数值,就可以了。(所以,这个地方就要求,间距必须是m, 这样通过rand_m 才能覆盖两个间距的所有的数,同时对于生成的起点,也是只有一种可能)

 

就如同,本题目,按照这个公式,我们就可以等概率地生成1~49间的所有数了。(7*6+7, 最大范围),那如何生成1--10呢。其实,等概率地生成1~49, 就可以等概率地生成1~10,我们最简单的方法,可以直接判断这个结果是否在1~10之间就可以,如果不在,就重新再试一次。但是这样速度可能比较慢。所以我们可以在1~m*m 中,挑选几组 1~10,也就是可以是 1~10,11~20, 。。。,这样就可以更快地得到我们的结果。

所以我觉得下面这个程序写的不错,就是上面链接中的程序。

 

int random_n()

{

int val = 0 ;

int t; // t为n最大倍数,且满足 t <= m * m

do {

    val = m * (random_m() - 1) + random_m();

} while (val > t);

return val;
}

 可以略微对val处理一下。

 

2012-03-01

 方法2:

例如Rand7会生成1,2,3,4,5,6,7这些数。我们以4为分界点。

如果生成1-3这3个数字时,我们在Rand7,只取1-5这几个数字。

如果生成5-7这3个数字时,我们在Rand7+3,只取5-10这几个数字。

 

 

方法3:

例如Rand7会生成1,2,3,4,5,6,7这些数。我们以4为分界点。

由于 rand7 是 1..7

rand7+3是 4..10, 直接返回结果时,4..7 的概率会多一倍

全局标志位 flag = 0; 记录每当出现再次4..7时才进行输出

1.如果生成1-3这3个数字时,我们在Rand7

 1.1如果生成1-3,直接输出

 1.2如果生成4-7,如果flag=0, 则置flag = 1, 再调用一次Rand10.

                          flag = 1, 直接返回此值, flag = 0

 

2.如果生成5-7这3个数字时,我们在Rand7+3,只取5-10这几个数字。

 同理

 

在编程中,生成随机向量通常涉及到随机数生成函数。以C语言为例,`rand()` 函数可以用来生成随机数,它被包含在`stdlib.h`头文件中。如果你想要生成两个各有 `m` 个元素的向量,并用随机数填充它们,你可以按照以下步骤进行: 1. 引入必要的头文件,如 `stdlib.h`(用于 `rand()`)和 `time.h`(用于 `srand()` 和 `time()`,初始化随机数生成器)。 2. 使用循环来为每个向量的每个元素调用 `rand()` 函数。 3. 为了保证每次程序运行时生成的随机数序列不同,通常使用 `srand(time(NULL))` 来设置随机数种子。 下面是一个简单的C语言代码示例,展示如何生成这样的向量: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define M 10 // 假设向量长度为10 void generateRandomVector(int vector[], int size) { for (int i = 0; i < size; ++i) { vector[i] = rand() % 100; // 生成0到99之间的随机数 } } int main() { int vector1[M]; int vector2[M]; // 初始化随机数生成器 srand((unsigned int)time(NULL)); // 生成两个向量 generateRandomVector(vector1, M); generateRandomVector(vector2, M); // 打印向量内容 printf("Vector 1:\n"); for (int i = 0; i < M; ++i) { printf("%d ", vector1[i]); } printf("\n"); printf("Vector 2:\n"); for (int i = 0; i < M; ++i) { printf("%d ", vector2[i]); } printf("\n"); return 0; } ``` 在这个例子中,我们定义了一个 `generateRandomVector` 函数来填充向量。`rand() % 100` 表示生成一个0到99之间的随机整数。你可以根据需要调整生成的随机数范围。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值