32

Python Docsを調べましたが(誤解しているかもしれません)、再帰関数を呼び出さずにこれを行う方法(以下を参照)があるとは思いませんでした。
私がやりたいのは、真ん中の値を除外したランダムな値を生成することです。

言い換えれば、私がにない乱数
になりたかったと想像してみましょう。 最初のパスでこれを行うことはできますか、または 1. 常に番号を生成する 必要があり ますか?X
range(a - b, a + b)



range()

再帰関数を書きたくない理由については、
1。「そうする必要はない」のように感じます
。2。これを行っている数値のセットは、実際にはかなり大きくなる可能性があり
ます。スタックオーバーフローが悪いと聞きました。これを行う際には、過度に慎重になっている可能性があります。

私はそれを行うための素晴らしい、Pythonic、非再帰的な方法があると確信しています。

4

7 に答える 7

43

1つの乱数を生成し、それを目的の数の範囲にマップします。

とを除いて、1-4またはの間の整数を生成したい場合は、次のようになります。7-1056

  1. 範囲内のランダムな整数を生成します1-8
  2. 乱数が4より大きい場合は2、結果に追加します。

マッピングは次のようになります。

Random number:    1  2  3  4  5  6  7  8
Result:           1  2  3  4  7  8  9 10

このようにすると、「リロール」する必要がなくなります。上記の例は整数用ですが、floatにも適用できます。

于 2012-05-19T16:06:34.593 に答える
31

random.choice()を使用します。この例では、aが下限、bとcの間の範囲がスキップされ、dが上限です。

import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
于 2012-05-19T15:56:41.267 に答える
9

考えられる解決策は、乱数をその範囲からシフトすることです。例えば

def NormalWORange(a, b, sigma):
    r = random.normalvariate(a,sigma)
    if r < a:
        return r-b
    else:
        return r+b

これにより、範囲(ab、a + b)に穴がある正規分布が生成されます。

編集:整数が必要な場合は、もう少し作業が必要になります。[c、ab]または[a + b、d]の範囲の整数が必要な場合は、次の方法でうまくいくはずです。

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
于 2012-05-19T16:03:47.300 に答える
7

私はあなたの問題を誤解したかもしれませんが、再帰なしでこれを実装することができます

def rand(exclude):
    r = None
    while r in exclude or r is None:
         r = random.randrange(1,10)
    return r

rand([1,3,9])

ただし、新しい結果が見つかるまで、結果をループし続けています。

于 2012-05-19T15:56:48.793 に答える
4

最速の解決策は次のとおりです(aとbは除外ゾーンを定義し、cとdは除外ゾーンを含む一連の適切な回答を定義します)。

offset = b - a
maximum = d - offset
result = random.randrange(c, maximum)
if result >= a:
    result += offset
于 2012-05-19T15:56:12.440 に答える
0

あなたはまだいくつかの範囲、すなわちあなたの中間値を除いた最小-最大の可能な値を必要とします。

最初に範囲の「半分」をランダムに選択してから、その範囲内の乱数を選択してみませんか?例えば:

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)
于 2012-05-19T15:58:58.060 に答える
0

Li-aung Yipの答えは再帰の問題を議論の余地のあるものにしますが、スタックを気にせずに任意の程度の再帰を実行できることを指摘する必要があります。これは「末尾再帰」と呼ばれます。Pythonは末尾再帰を直接サポートしていません。これは、GvRが末尾再帰をクールではないと考えているためです。

http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html

しかし、これを回避することができます:

http://paulbutler.org/archives/tail-recursion-in-python/

スティックが再帰が「気分が悪い」と考えるのは面白いと思います。Schemeのような非常に機能指向の言語では、再帰は避けられません。関数型プログラミングパラダイムが厳密に回避する状態変数を作成せずに反復を実行できます。

http://www.pling.org.uk/cs/pop.html

于 2012-05-20T19:07:30.147 に答える