Python是否可以生成排除一组数字的随机数,而不使用递归?
我仔细看了一下(我可能误解了),但我没有发现有一种方法可以不用调用递归函数就可以做到这一点(请看下面)。Python是否可以生成排除一组数字的随机数,而不使用递归?,python,recursion,random,range,Python,Recursion,Random,Range,我仔细看了一下(我可能误解了),但我没有发现有一种方法可以不用调用递归函数就可以做到这一点(请看下面)。 我想做的是生成一个随机值,排除中间值。< /P> 换句话说, 让我们想象一下,我希望X是一个不在 范围(a-b,a+b) 我可以在第一次通过时这样做吗, 或 1.我是否必须不断生成一个数字, 2.检查是否在范围(), 3.洗漱 至于我为什么不想写递归函数, 1.“感觉上”我不应该这样做 2.我这样做的结果可能会非常大, ... 我听说堆栈溢出很糟糕,我可能只是在这样做时过于谨慎了 我确信有一
我想做的是生成一个随机值,排除中间值。< /P> 换句话说,
让我们想象一下,我希望
X
是一个不在范围(a-b,a+b)
我可以在第一次通过时这样做吗,
或
1.我是否必须不断生成一个数字,
2.检查是否在
范围()
,3.洗漱 至于我为什么不想写递归函数,
1.“感觉上”我不应该这样做
2.我这样做的结果可能会非常大,
... 我听说堆栈溢出很糟糕,我可能只是在这样做时过于谨慎了
我确信有一种很好的、python式的、非递归的方法可以做到这一点。最快的解决方案是这样的(a和b定义了排除区,c和d定义了一组好的答案,包括排除区): 使用random.choice()。 在本例中,a是下限,跳过b和c之间的范围,d是上限
import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
我可能误解了您的问题,但您可以实现它而无需递归
def rand(exclude):
r = None
while r in exclude or r is None:
r = random.randrange(1,10)
return r
rand([1,3,9])
不过,在找到新的结果之前,您仍在循环搜索结果。您仍然需要一些范围,即不包括中间值的最小-最大可能值
你为什么不先随机选择你想要的范围的“一半”,然后在该范围内选择一个随机数?例如:
def rand_not_in_range(a,b):
rangechoices = ((0,a-b-1),(a+b+1, 10000000))
# Pick a half
fromrange = random.choice(rangechoices)
# return int from that range
return random.randint(*fromrange)
一个可能的解决方案是将随机数移出该范围。例如
def NormalWORange(a, b, sigma):
r = random.normalvariate(a,sigma)
if r < a:
return r-b
else:
return r+b
生成一个随机数并将其映射到所需的数字范围 如果要生成介于
1-4
或7-10
之间的整数(不包括5
和6
),可以:
1-8
2
Random number: 1 2 3 4 5 6 7 8
Result: 1 2 3 4 7 8 9 10
这样做,你永远不需要“重新滚动”。上面的例子是针对整数的,但它也可以应用于浮点。李昂业的回答使递归问题变得毫无意义,但我必须指出,可以在不担心堆栈的情况下进行任何程度的递归。这叫做“尾部递归”。Python不直接支持尾部递归,因为GvR认为它不酷: 但你可以绕过这一点: 我觉得有趣的是,stick认为递归“感觉不对”。在面向函数的语言中,如Scheme,递归是不可避免的。它允许您在不创建状态变量的情况下进行迭代,函数式编程范式严格避免了这种情况
除非可能的答案集非常大,否则这将起作用,在这种情况下,它将使用太多内存并崩溃。@AndrewG:同意,如果范围大小为数百万/数十亿,这并不理想。另一方面,它简单而难忘。你的答案,虽然是一个非常好和健壮的解决方案,但可能更容易出错。如果从一开始就知道a、b、c和d是一个小集合,我会使用你的答案;如果它们依赖于输入或已知是一个大集合,我会使用我的答案。@ihavenoidia:
range
始终包括第一个参数,排除第二个参数。因此,在我的示例中,numbers
是[a,b)+[c,d]。可能需要将其写成numbers=list(范围(a,b))+list(范围(c,d))
这将在这两个范围之间得到50/50的分布,不管它们相对而言有多大。嗯,在代码的最后一部分中一定有逻辑错误——现在尝试调试它……哦。它应该是offset=b-a。编辑。它也应该是result>=a。好了,应该是这样的。+1用于很好的解释——这是我想说的是什么,但我发现仅仅用代码无法解释。@AndrewG:谢谢。:)用几张图片就可以更好地解释,但今晚我打开Visio的激活能量有点高。;)非常感谢你,它的执行非常直接,并激励读者在而不是简单地发布代码并说“来,运行这个。”最后,我使用了Junuxx的解决方案,但我也欣赏这个答案的优雅。作为一个编程新手,这完全是我需要阅读的内容。谢谢!我不一定对递归过敏,说实话,我没有意识到,就连Python的BDFL也普遍对它表示蔑视;我只是有一个g但是我觉得我不需要在这个特定的项目中使用它。我不会排除在未来的努力中使用它。嘿,如果我的答案有用,请投票吧!我需要声誉。我以为我有。我的错误:)
def RangeWORange(a, b, c, d):
r = random.randrange(c,d-2*b) # 2*b because two intervals of length b to exclude
if r >= a-b:
return r+2*b
else:
return r
Random number: 1 2 3 4 5 6 7 8
Result: 1 2 3 4 7 8 9 10