美文网首页
将生成1-5随机数函数转换为1-7随机数函数的实现方法

将生成1-5随机数函数转换为1-7随机数函数的实现方法

作者: 流月0 | 来源:发表于2017-11-18 16:18 被阅读0次

个人技术博客地址:http://songmingyao.com/


问题

现有一个生成1-5随机数的函数random_5(概率平均),如何将此转换为生成1-7随机数random_7的函数(概率平均),不得使用random模块

思路一(False)

直接将random_5生成的随机数乘以7/5后再通过round函数进行四舍五入后输出

random_5输出 random_7输出
1 1
2 3
3 4
4 6
5 7

特别糟糕的想法...

思路二(False)

生成两次random_5,将两者的值相加后减一(random_5 + random_5 - 1),得出随机数1-9,而后再做一次判断,将8和9剔除掉,只在返回1-7的时候输出

不过很快就发现,只有在两次random_5都返回1的时候,才会返回1,概率远小于返回其它六个数

又是一个糟糕的想法...

思路三(True)

  • 通过之前的两种思路,可以总结出将random_5返回的数据经过各种处理后不筛选返回1-7是不可能实现的(不能说不可能,只是我个人能力有限,暂时还没想出方法),那必须采用思路二中的筛选方法。
  • 确定要使用筛选方法之后,目标就变成了生成等概率的、值取值范围大于1-7的随机数。
  • 相加和返回值乘系数的方法都尝试过了,那么是否可以将两者结合一下呢。
  • 首先思考乘系数,random_5 * 2 - 1的返回结果是[1, 3, 5, 7, 9],想要等概率生成1-10的话,比如再将此返回值加上随机生成的0和1,也就是random.randint(0, 1)
  • 因不允许使用random模块,所以我们必须想办法重复利用原有的random_5函数,random_5 * 3 - 2需要对应的random.randint(0, 2),也可以理解为random.randint(1, 3) - 1
  • 此时,显而易见,random_5 * 5 - 4需要对应的random.randint(1, 5) - 1,也就是random_5 - 1,那么基本的函数体就出来了,就是
random_5 * 5 + random_5 - 5
  • 再将筛选的逻辑加进去,完整代码如下:
import random


# 原有生成1-5随机数的函数
def random_5():
    return random.randint(1, 5)


# 要获得的生成1~7随机数的函数
def random_7():
    while True:  # 避免没有返回值
        n = (random_5()-1)*5 + random_5()-1  # 生成0~24的随机数
        if n <= 20:
            return n % 7 + 1


if __name__ == '__main__':
    print(random_7())

进阶

刚才得出的核心代码,去掉常变量之后就变成了random_5 * 5 + random_5,看着很像二、八、十六进制转换为十进制的方法,也就是可以理解为五进制,通过这种思想我们可以得出一个通用的随机数转换方法,具体代码如下:

import random
import math


class RandomIJToRandomAB(object):
    """将原来i-j之间的随机数生成函数,转化为a-b之间的随机数生成函数"""
    def __init__(self, i, j):
        self.i = i
        self.j = j
        ij_dif = j-i

        if ij_dif <= 0:
            raise ValueError

        self.ij_dif = ij_dif

    def random_ij(self):
        return random.randint(0, self.ij_dif)

    def random_ab(self, a, b):
        ab_dif = b-a
        digit = int(math.ceil(math.log(ab_dif+1, self.ij_dif+1)))  # 获取差值(ab_dif)转换为ij_dif+1进制后的最大位数

        while True:  # 防止return None
            # 生成最大位数为digit的ij_dif+1进制随机数,而后转化为10进制
            random_res = 0
            for item in range(digit):
                random_res += self.random_ij() * pow(self.ij_dif+1, item)

            # 只取在区间范围内的随机数
            if random_res <= ab_dif:
                return random_res+a


if __name__ == '__main__':
    print('0~1随机生成函数转化为2~11随机生成函数')
    random_1 = RandomIJToRandomAB(0, 1)
    print(random_1.random_ab(2, 11))
    print('-'*50)

    print('1~5随机生成函数转化为1~7随机生成函数')
    random_1_5 = RandomIJToRandomAB(1, 5)
    print(random_1_5.random_ab(1, 7))
    print('-'*50)

    print('1~7随机生成函数转化为1~5随机生成函数')
    random_1_7 = RandomIJToRandomAB(1, 7)
    print(random_1_7.random_ab(1, 5))
    print('-'*50)

Github源码地址:

random5_to_random7:
https://github.com/shelmingsong/algorithm_practice/blob/master/31_random5_to_random7_20170824.py

random_ij_to_random_ab:
https://github.com/shelmingsong/algorithm_practice/blob/master/32_random_ij_to_random_ab_20170824.py

相关文章

  • 随机数生成器

    题目:有一个随机数函数,可以生成1-7的数字,现在要求利用这个函数生成一个1-10的随机数函数。思路:这道题网络上...

  • 将生成1-5随机数函数转换为1-7随机数函数的实现方法

    个人技术博客地址:http://songmingyao.com/ 问题 现有一个生成1-5随机数的函数random...

  • 生成随机数

    两个C函数 rand()函数生成的随机数是伪随机数,所谓伪随机数,指的是程序每次运行,生成的随机数都是不变的,生成...

  • Python Random库的使用

    random库用于生成随机数 基本随机数函数: seed(), random() 扩展随机数函数: randint...

  • 今日头条面试题:生成随机数(根据rand5()生成rand7()

    题目描述 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数。 (即,使用函数rand5()来实现...

  • 均匀分布随机函数的实现

    前言 随机函数就是产生数的函数,C语言里使用rand(),srand()等随机函数实现随机数生成。 函数简介 in...

  • 随机数 arc4random_uniform

    Objective-C 中有个arc4random()函数用来生成随机数,但是这个函数生成的随机数范围比较大,需要...

  • arc4random_uniform

    Objective-C 中有个arc4random()函数用来生成随机数且不需要种子,但是这个函数生成的随机数范围...

  • 利用arc4random_uniform()产生随机数

    Objective-C 中有个arc4random()函数用来生成随机数且不需要种子,但是这个函数生成的随机数范围...

  • C++随机数

    C++ 随机数 在许多情况下,需要生成随机数。关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返...

网友评论

      本文标题:将生成1-5随机数函数转换为1-7随机数函数的实现方法

      本文链接:https://www.haomeiwen.com/subject/zpnevxtx.html