范围大随机数与范围小随机数相互转化--算法学习(三)


在实际应用中经常会模拟随机数的输入,在软件语言如c/python中,采用rand()/数范围 即可得到随机数。但是很多情况下也会用到由已知一定范围的随机数转化成另一范围随机数,一个问题是 是否是一个随机数转化成另一个随机数,不允许丢数,分两种情况阐述。

一、 允许丢数,不同范围随机数转化

这种一般适用于已知随机数,不严格要求每一个随机都转化出去。实际应用起来比较简单,只要能保证输出随机数足够随机,便符合要求。

1.1 小范围随机数转化为大范围随机数

题目:给定一个随机数生成器,这个生成器能均匀生成1到5(1,5)的随机数,如何使用这个生成器生成均匀分布的1到7(1,7)的数?

方法一:生成两个(1,5)的随机数,这样一共是25种情况,注意这两个数是有顺序的,从这25种情况中,取前21种,每三种代表(1,7)中的一个数字,如果取到的是这21种以外的情况,丢掉重新取。

方法二:生成三个(1,5)的随机数,分别表示一个二进制位,其中1和2映射为0,3跳过,4和5映射为1。这样产生的三位二进制数,即1-8这8个数字都是等概率的。如果产生的是8,那么丢弃即可。

方法三:生成两个(1,5)的随机数,产生一个两位的五进制数,5 * (random5() – 1) + random5()。这个公式能够等概率产生1-25,即第一个随机数代表:0,5,10,15,20,地位代表1,2,3,4,5。这样对这个数字(1-25的数字),采用方法一的方法,只用1-21,分7分,代表1-7,22-25这4个数字扔掉。

如果允许丢弃数据,以及允许多次产生多组原始随机数,产生新的随机数方法很多,并不难想到方法,不展开叙述。

题目:已知random3()这个随机数产生器生成[1, 3]范围的随机数,请用random3()构造random5()函数,生成[1, 5]的随机数?

int random5()
{
    int val = 0;
    do {
        val = 3 * (random3() - 1) + random3();
    } while (val > 5);
    return val;
}
1.2 大范围随机数转化为小范围随机数

题目:假设你有一个能产生1-49范围的随机数的函数,怎么产生1-10范围内的随机数呢?

解决方法基于接受—拒绝采样(Rejection Sampling)原理。主要思路是,当你产生的数在想要的范围内,直接输出,*如果产生的数不在想要的范围内,拒绝这个数重新采样。*我们想要的范围内的数被取到的概率是一样的,结果就是均匀分布。

int rand10()
{
    int row, col, idx;
    do
    {
        row = rand7();
        col = rand7();
        idx = col + (row-1)*7;
    }
    while (idx > 40);
 
    return 1 + (idx-1)%10;
}
二、 不允许丢数,不同范围随机数转化

此种方式较为复杂,实际中可能产生一个随机数立刻就需要输出一个随机数,不允许丢数,来源也只是一个随机数输入。

2.1 小范围随机数转化为大范围随机数

题目:(0,191)范围内随机数转化为(0,255)范围内随机数

先看到(191+1)以及(255+1)都是64的倍数,采用Python生成随机代码如下,同时会把结果输入到excel表,可以观察到结果随机。

import xlwt
import random
book=xlwt.Workbook(encoding='utf-8',style_compression=0)
sheet=book.add_sheet('random_num_count')   #创建一个sheet
sheet.write(0,0,"rand")
sheet.write(0,1,"cnt")

big_index={}
for i in range(0,256):
    big_index[i]=0
for j in range(0,300000):
    rand=random.randint(0,191)
    new=(rand/3+1)*4-(j%4+1)         #(j%4+1)加入新的随机量
    big_index[new]=big_index[new]+1
for i in range(0,256):
    sheet.write(i+1,0,int(i))
    sheet.write(i+1,1,big_index[i])
book.save('C:/users/Desktop/random_num_count.xls')

可以直接运行,这里采用的(j%4+1)加入随机参数,如果没有上面range(0,300000)范围也可以累加(0,1,2,3)累加溢出。

2.2 大范围随机数转化为小范围随机数

题目:(0,255)范围内随机数转化为(0,191)范围内随机数

import xlwt
import random
book=xlwt.Workbook(encoding='utf-8',style_compression=0)
sheet=book.add_sheet('random_num_count')   #创建一个sheet
sheet.write(0,0,"rand")
sheet.write(0,1,"cnt")

small_index={}
for i in range(0,256):
    small_index[i]=0
for j in range(0,300000):
    rand=random.randint(0,255)
    if rand <= 191:
        small_index[rand]=small_index[rand]+1
    else:
    new=(rand-191)*3-(j%3+1)         #(j%4+1)加入新的随机量
    small_index[new]=small_index[new]+1
for i in range(0,192):
    sheet.write(i+1,0,int(i))
    sheet.write(i+1,1,small_index[i])
book.save('C:/users/Desktop/random_num_count.xls')

代码手敲,难免手误,如果有运行问题欢迎留言,其他问题也欢迎留言交流。

参考文档

【1】随机数产生转换-根据(1,5)随机数生成器,生成(1,7)之内的随机数

【2】随机数产生函数的范围转换

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Paul安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值