两种经典方法解决随机数生成问题--利用rand5得到rand7

文章介绍了如何使用Python中的random模块和二进制移位运算,通过类Rand2rand和类Rand2randGeneral,实现从1到N和更大范围的等概率随机数生成。方法包括利用randN函数结合特定算式生成指定区间内的随机数。
摘要由CSDN通过智能技术生成

两种方法:

  • 等概率得到0和1,然后利用二进制移位运算生成随机数
  • 基于N * (randN - 1) + randN,可以等概率地生成1-N*N之间的数字

利用rand5得到rand7 为例说明

# 一个函数可以实现1-5的随机数,设计另一个函数,实现1-7的随机数
class Rand2rand:
    def f5(self):
        return int(random.random() * 5) + 1

    # 等概率得到0和1
    def g01(self):
        while True:
            tmp = self.f5()
            if tmp < 3:
                return 0
            elif tmp > 3:
                return 1
            else:
                continue

    # 等概率得到0-6
    def f06(self):
        while True:
            tmp = (self.g01() << 2) + (self.g01() << 1) + (self.g01() << 0)
            if tmp == 7:
                continue
            else:
                return tmp

    # 等概率得到1-7
    def f17(self):
        return self.f06() + 1

    # 验证结果
    def testRes(self, testTimes: int, rand_generator):
        arr = [0] * 7
        for i in range(testTimes):
            tmp = rand_generator()
            arr[tmp - 1] += 1

        for i in range(len(arr)):
            print(f'{i + 1} 出现了 {arr[i]} 次')

    def f17_2(self):
        # 5*(self.f5()-1) 等概率产生 0, 5, 10, 15, 20
        # self.f5() 等概率产生 1,2,3,4,5
        # 想加后,等概率产生 1-25

        # rand5()可以得到rand25()
        # rand25()可以得到rand625()

        # 总结,若randN() 可以随机生成1-N,那么N*(randN()-1) + randN() 可以随机生成 1-N**2

        randVal = 22
        while randVal > 21:
            randVal = 5 * (self.f5() - 1) + self.f5()
        return 1 + randVal % 7

# 结果验证
if __name__ == '__main__':
	obj = Rand2rand()
    rand_gen1 = obj.f17
    rand_gen2 = obj.f17_2
    obj.testRes(1000000, rand_gen2)


class Rand2randGeneral:
    """
    更一般的问题,给定一个可以产出[min, max]之间的等概率随机数函数,
    生成一个可以等概率生成[from, to]之间的随机数函数
    """

    def __init__(self, min, max):
        self.min = min
        self.max = max

    def randomBox(self):
        diff = int(random.random() * (self.max - self.min + 1))
        randomValue = self.min + diff
        return randomValue

    def getrand01(self):
        size = self.max - self.min + 1

        # 判断size 是奇数还是偶数
        isOdd = True if (size & 1) != 0 else False
        mid = int(size / 2)

        while True:
            ans = self.randomBox() - self.min
            if isOdd and ans == mid:
                continue
            elif ans < mid:
                return 0
            else:
                return 1

    def getRandGeneral(self, fromValue, toValue):
        if fromValue == toValue:
            return fromValue

        rangeVal = toValue - fromValue
        num = 1
        while (1 << num) - 1 < rangeVal:
            num += 1

        while True:
            ans = 0
            for i in range(num):
                ans |= self.getrand01() << i
            if ans > rangeVal:
                continue
            else:
                return ans + fromValue


  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NLP_wendi

谢谢您的支持。

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

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

打赏作者

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

抵扣说明:

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

余额充值