【问题标题】:Random number that is divisible by N [duplicate]可被 N 整除的随机数 [重复]
【发布时间】:2019-10-01 02:06:19
【问题描述】:

我想从范围 [a,b] 中生成一个可被 N 整除的随机数(在我的情况下为 4)。 我有解决方案,但有更好(更优雅)的方法吗?

result = random.randint(a, b)
result = math.ceil(result / 4) * 4

这里的解决方案: Python: Generate random number between x and y which is a multiple of 5 没有回答我的问题,因为我必须实现类似的东西:

random.randint(a, b) * 4;

我必须将原始范围除以 4,它的可读性不如我原来的解决方案

【问题讨论】:

  • 您的解决方案是错误的。例如如果 a=1, b=15,您的解决方案可能会给出 16,这是错误的
  • “除以 N 的数字”不是合法的英语,而“除以 N 的数字”是另一回事。我认为您的意思是“可被N整除的数字”
  • @DYZ 请查看我对您提到的重复解决方案的评论

标签: python python-3.x


【解决方案1】:

一个通用的解决方案和一个例子

import random

def divisible_random(a,b,n):
    if b-a < n:
      raise Exception('{} is too big'.format(n))
    result = random.randint(a, b)
    while result % n != 0:
      result = random.randint(a, b)
    return result
# get a random int in the range 2 - 12, the number is divisible by 3
print(divisible_random(2,12,3))

【讨论】:

  • 简单通用,谢谢!
  • 可能值得一提的是,这个可能真的很慢,甚至在极端情况下会导致无限循环。
  • 这很容易陷入无限循环,print(divisible_random(2,5,3))@KocT9H
  • 我同意陷入无限循环的选项。应该为函数添加额外的保护。
  • 感谢您指出。我添加了一个计数器来停止循环并在计数器为 0 时返回 (result // 4 * 4)。
【解决方案2】:

我首先想到的是在给定的时间间隔内使用range 创建所有可能选择的列表,然后使用choice 随机选择一个值。

因此,在这种情况下,对于给定的 ab

random.choice(range(a + 4 - (a%4), b, 4))

如果a是4的完美倍数,那么

random.choice(range(a, b, 4))

会给你所需的随机数。

因此,在单个泛型函数中,(如 cmets 中所建议的)

def get_num(a, b, x):
    if not a % x:
        return random.choice(range(a, b, x))
    else:
        return random.choice(range(a + x - (a%x), b, x))

其中x 是需要其倍数的数字。

【讨论】:

  • 我正要发布这个。 +1
  • 解决方法错误:random.choice(range(5 + (5%4), 7, 4)) 产生 6,效率也很低。
  • @DYZ 错过了,现在更正
  • 您可能希望将此逻辑包装在单个函数中...
  • @DYZ:由于Divyanshu对range创建列表有错误,所以效率其实还可以。
【解决方案3】:

正如其他人指出的那样,您的解决方案可能会产生超出范围的结果,例如math.ceil(15 / 4) * 4 == 16。此外,请注意生成的分布可能与均匀分布相去甚远。例如,如果a == 0b == 4,则在 80% 的情况下生成的数字将为 4。 除此之外,这对我来说似乎不错,但是在 Python 中,您也可以只使用整数除法运算符(实际上是地板除法,因此它不等同于您的示例):

result = random.randint(a, b)
result = result // 4 * 4

但是一种更通用但效率较低的生成具有特定约束的均匀随机数(同时也保持均匀分布)的方法是在循环中生成它们,直到找到一个好的方法:

result = 1
while result % 4 != 0:
    result = random.randint(a, b)

【讨论】:

    【解决方案4】:

    使用random.randrange,步长为n,如果a不能被n整除,则使用a+n-(a%n)作为开始,否则使用a作为开始

    import random
    
    def rand_n(a, b,n):
    
        #If n is bigger than range, return -1
        if n > b-a:
            return -1
    
        #If a is divisible by n, use a as a start, using n as step size
        if a%n == 0:
            return random.randrange(a,b,n)
    
        # If a is not divisible by n, use a+n-(a%n) as a start, using n as step size
        else:
            return random.randrange(a+n-(a%n),b, n)
    

    【讨论】:

    • 现在这有什么问题?
    • 错误如下,例如如果 a=0,尽管可以接受,但永远不会选择 0。
    • 遇到错误 def rand_n(a, b, 4): ^ SyntaxError: invalid syntax
    • 您在函数中可以互换使用 n 和 4。
    • 仍然错误。让我帮你修。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多