如何产生 [0, 2147483647] 之间的随机数 - GoAgent - 博客园
一、简介
随机数是编程中经常要用到的东西,但很遗憾的是在windows下vc和MinGW中的 RAND_MAX 都是32767,
也就是说调用系统的rand()函数只能产生范围在[0, 32767]之间的随机数。
那如何得到范围达到[0, 2147483647]的随机数呢?
二、最直观的方法
最直接的想法显然是调用rand()生成更大区间的随机数,比如两个rand()相加或者相乘,但是,
两个rand()相加时,越大的数出现的概率越高,因为2=2+0=1+1=0+2,而5=0+5=1+4=2+3=3+2=4+1=5+0;
两个rand()相乘时,是永远不可能得到更大区间范围内的质数的,比如两个[0, 4]范围内的随机数相乘的所有组合都不可能得到7。
综上,似乎要寻找一种更靠谱的方法。
三、基于按位随机的随机数产生方法
首先我们知道,由一个较大的区间产生较小区间的随机数是十分方便的,只要把多余的数剔除掉,然后等分区间就可以了。
比如,由[0, 17]之间的随机数发生器A产生[0, 2]之间的随机数发生器B,只需要将 A 做一个映射:
[0, 4] --> 0
[5, 9] --> 1
[10, 14] --> 2
[15, 17] --> 丢弃
这样0、1、2出现的概率都是相等的,对于A而言都是5/18,对于B而言都是1/3。
特别的,给定任意一个随机数发生器A(产生[0, m]之间的随机数,m>0),一定能用这个随机数发生器产生[0, 1]的随机数发生器B:
m=1时A即为[0, 1]随机数发生器,m>1时,
若m为奇数,则将A产生的数直接%2;若m为偶数,若A产生的数等于m则丢弃,其它情况直接%2。
这样就得到了[0, 1]随机数发生器B。
那么,无论我们需要的随机数范围有多大,只要按位随机出0或者1,那么这个数一定随机的。
比如需要[0, 2147483647]之间的随机数,那么只要按位随机出31个二进制位,那么就得到了[0, 2147483647]之间的随机数。
Read full article from 如何产生 [0, 2147483647] 之间的随机数 - GoAgent - 博客园
一、简介
随机数是编程中经常要用到的东西,但很遗憾的是在windows下vc和MinGW中的 RAND_MAX 都是32767,
也就是说调用系统的rand()函数只能产生范围在[0, 32767]之间的随机数。
那如何得到范围达到[0, 2147483647]的随机数呢?
二、最直观的方法
最直接的想法显然是调用rand()生成更大区间的随机数,比如两个rand()相加或者相乘,但是,
两个rand()相加时,越大的数出现的概率越高,因为2=2+0=1+1=0+2,而5=0+5=1+4=2+3=3+2=4+1=5+0;
两个rand()相乘时,是永远不可能得到更大区间范围内的质数的,比如两个[0, 4]范围内的随机数相乘的所有组合都不可能得到7。
综上,似乎要寻找一种更靠谱的方法。
三、基于按位随机的随机数产生方法
首先我们知道,由一个较大的区间产生较小区间的随机数是十分方便的,只要把多余的数剔除掉,然后等分区间就可以了。
比如,由[0, 17]之间的随机数发生器A产生[0, 2]之间的随机数发生器B,只需要将 A 做一个映射:
[0, 4] --> 0
[5, 9] --> 1
[10, 14] --> 2
[15, 17] --> 丢弃
这样0、1、2出现的概率都是相等的,对于A而言都是5/18,对于B而言都是1/3。
特别的,给定任意一个随机数发生器A(产生[0, m]之间的随机数,m>0),一定能用这个随机数发生器产生[0, 1]的随机数发生器B:
m=1时A即为[0, 1]随机数发生器,m>1时,
若m为奇数,则将A产生的数直接%2;若m为偶数,若A产生的数等于m则丢弃,其它情况直接%2。
这样就得到了[0, 1]随机数发生器B。
那么,无论我们需要的随机数范围有多大,只要按位随机出0或者1,那么这个数一定随机的。
比如需要[0, 2147483647]之间的随机数,那么只要按位随机出31个二进制位,那么就得到了[0, 2147483647]之间的随机数。
Read full article from 如何产生 [0, 2147483647] 之间的随机数 - GoAgent - 博客园