给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?
题目:给定一个函数rand()能产生1到n之间的等概率随机数,问如何产生1到m之间等概率的随机数?
先把问题特殊化,例如原题变为给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一样。现要求使用该函数构造函数rand7(),使函数rand7()可以随机等概率的生成1-7的整数。
很多人的第一反应是利用rand5() + rand()%3来实现rand7()函数,这个方法确实可以产生1-7之间的随机数,但是仔细想想可以发现数字生成的概率是不相等的。rand()%3 产生0的概率是1/5,而产生1和2的概率都是2/5,所以这个方法产生6和7的概率大于产生5的概率。
正确的方法是利用rand5()函数生成1-25之间的数字,然后将其中的1-21映射成1-7,丢弃22-25。例如生成(1,1),(1,2),(1,3),则看成rand7()中的1,如果出现剩下的4种,则丢弃重新生成。
现在来看原题把rand()视为N进制的一位数产生器,那么可以使用rand()*N+rand()来产生2位的N进 制数,以此类推,可以产生3位,4位,5位...的N进制数。这种按构造N进制数的方式生成的随机数,必定能保证随机概率平均。而相反,借助其他方式来使用 rand()产生随机数(如 rand5() + rand()%3 )都是不能保证概率平均的。
程序实现:
int random(int m,int n)
{
if(n<||m<)//输入参数错误
return -;
if(m<)//小于2则只能生成1
return ;
if(m==n)//和n相同即可
return rand();
int max = ;//组成新n进制数当前位数下最大数
int k = ;//随机数
while(max+<m)//求得新n进制数当前位数下最大数小于m,则继续放大新n进制数的位数
{
k = k*n + rand()-;//转换成0到n-1的n进制数。一位时0到n-1,两位时0到(n-1)*n+n-1。此时保证了生成0到最大数之间的各个数的概率是相等的
max = max*n + n-;//求n进制数当前位数下的最大数。一位数时n-1,两位数时(n-1)*n+n-1,三位数时(n-1)*n*n+(n-1)*n+n-1
//随机数超出了范围则重新计算。除m再乘m是为了对生成的k进行分组
//如m=7,n=5时此处k的范围是0到24,那么25/7=3,3*7=21。
//因为21、22、23、24都需要重新计算,所以后面返回值k/((max+1)/m)+1就能保证最大值为7了,即20、19、18除3加1都等于7
//此处也可以不进行分组,直接限定k+1<=m后面返回k即可,这样得到k的概率也是一样的,只不过更不容易得到k,因为大量的k将大于m
if(max+>=m && k>=(max+)/m*m)
{
k = ;
max = ;
}
}
return k/(max+/m)+;//由上面逻辑保证了在1到m之间且各数生成概率相等
}
给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?的更多相关文章
- 面试题:给定一个函数rand()能产生1到m之间的等概率随机数,产生1到n之间等概率的随机数?
虽然TX的面试已经过去好几天了,然而惨痛的过程还历历在目.人生中第一次正式job面试就这么挂掉了.在于面试官的交流过程中,被问及了几个算法设计题,在今后几篇博文中,我一一总结与诸君分享. 1. 给定一 ...
- Java -- 给定一个int数组,拼接出最大数值
public class ZhiJieTiaoDong { /* 给定一个数组:组合成最大数值 */ public String szpj(int[] args){ if(null == args | ...
- 算法题——给定一个数组 arr,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
参考自:https://blog.csdn.net/qq_38200548/article/details/80688630 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] ...
- ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)
1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 154 Solved: 112[ ...
- 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况
用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...
- 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字符不改变,给定函数,编写函数 void Stringchang(const char*input,char*output)其中input是输入字符串,output是输出字符串
import java.util.Scanner; /*** * 1. 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字 ...
- 写一个函数,对于一个给定的整数,如果它的二进制模式从正向看和反向看是一样的,那么返回true;
写一个函数,对于一个给定的整数,如果它的二进制模式从正向看和反向看是一样的,那么返回true:也就是实现这样一个函数boolean isPalindrome(int x); 分析一下,该题目主要是通过 ...
- 给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回
给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回 //统计字符串中出现的字符的出现次数 public function strNum(){ ...
- 给定一个double类型的数组arr,其中的元素可正可负可0,返回子数组累乘的最大乘积。例如arr=[-2.5,4,0,3,0.5,8,-1],子数组[3,0.5,8]累乘可以获得最大的乘积12,所以返回12。
分析,是一个dp的题目, 设f[i]表示以i为结尾的最大值,g[i]表示以i结尾的最小值,那么 f[i+1] = max{f[i]*arr[i+1], g[i]*arr[i+1],arr[i+1]} ...
随机推荐
- VirtualBox下导入CentOS后,无法上网
从VirtualBox的"管理"菜单下,选择"导出虚拟电脑",存一个备份.用时,再从"管理"菜单下,选择"导入虚拟电脑&q ...
- POJ2406 Power Strings KMP算法
给你一个串s,如果能找到一个子串a,连接n次变成它,就把这个串称为power string,即a^n=s,求最大的n. 用KMP来想,如果存在的话,那么我每次f[i]的时候退的步数应该是一样多的 譬 ...
- DBSCAN算法
简单的说就是根据一个根据对象的密度不断扩展的过程的算法.一个对象O的密度可以用靠近O的对象数来判断.学习DBSCAN算法,需要弄清楚几个概念: 一:基本概念 1.:对象O的是与O为中心,为半径的空间, ...
- hdu 4701 Game 博弈论
思路: ▶ 设 win(i,x,y) 表示当前可以买的物品是 i,先手有 x 元,后 手有 y 元时,先手是否必胜 ▶ win(i,x,y) ⇐⇒∃j((j > i)∧(x ≥ si−sj)∧¬ ...
- 规范化ProjectEuler
Euler Level3 规范化程序: 包名:LevelX,X是等级 每题程序名:PE0xx.java,PE0xx.py 程序有必要的注释,不同方法运行结果也在程序中 规范化博文: 名字:Projec ...
- 什么叫非阻塞io
而一个NIO的实现会有所不同,下面是一个简单的例子: ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.re ...
- ios开发图片点击放大
图片点击放大,再次点击返回原视图.完美封装,一个类一句代码即可调用.IOS完美实现 创建了一个专门用于放大图片的类,以下为.h文件 #import <Foundation/Foundation. ...
- Windows下获取高精度时间注意事项
Windows下获取高精度时间注意事项 [转贴 AdamWu] 花了很长时间才得到的经验,与大家分享. 1. RDTSC - 粒度: 纳秒级 不推荐优势: 几乎是能够获得最细粒度的计数器抛弃理由: ...
- 69. Sqrt(x)
题目: Implement int sqrt(int x). Compute and return the square root of x. 链接: http://leetcode.com/pr ...
- 修改linux终端命令行颜色
进入修改:vim /root/.bashrc 1.PS1 要修改linux终端命令行颜色,我们需要用到PS1,PS1是Linux终端用户的一个环境变量,用来说明命令行提示符的设置.在终端输入命令:#s ...