私は Python Docs (誤解しているかもしれません)を見ましたが、再帰関数を呼び出さずにこれを行う方法(以下を参照)があることはわかりませんでした。
私がしたいことは、真ん中の値を除外するランダムな値を生成することです。
言い換えると、
私がX
に含まれていない乱数にしたいと想像してみましょうrange(a - b, a + b)
これを最初のパスで実行できますか、
または
1。常に番号を生成する必要がありますか、
2。 range()
かどうかを確認します。
3。リンスを洗う?
再帰関数を書きたくない理由は、
1。それは私がする必要はないはずの「のように感じる」
2。私がこれを行っている数のセットは、実際にはかなり大きくなる可能性があり、
...スタックオーバーフローが悪いと聞きましたが、これを行うことに過度に注意しているだけかもしれません。
私はそれを行うための素晴らしい、Pythonic、非再帰的な方法があると確信しています。
Random.choice()を使用します。この例では、aは下限、bとcの間の範囲はスキップされ、dは上限です。
import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
1つの乱数を生成し、それを目的の数値範囲にマッピングします。
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
このようにすると、「再ロール」する必要がなくなります。上記の例は整数の場合ですが、浮動小数点にも適用できます。
可能な解決策は、乱数をその範囲外にシフトすることです。例えば。
def NormalWORange(a, b, sigma):
r = random.normalvariate(a,sigma)
if r < a:
return r-b
else:
return r+b
これにより、範囲(a-b、a + b)の穴を持つ正規分布が生成されます。
編集:整数が必要な場合は、もう少し作業が必要になります。 [c、a-b]または[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
私はあなたの問題を誤解したかもしれませんが、再帰せずにこれを実装できます
def Rand(exclude):
r = None
while r in exclude or r is None:
r = random.randrange(1,10)
return r
Rand([1,3,9])
ただし、新しい結果が見つかるまで、結果を繰り返し処理しています。
最速のソリューションは次のようになります(aとbで除外ゾーンを定義し、cとdで除外ゾーンを含む適切な回答のセットを使用します)。
offset = b - a
maximum = d - offset
result = random.randrange(c, maximum)
if result >= a:
result += offset
Li-aung Yipの答えは再帰の問題を解決しますが、スタックを気にせずに任意の程度の再帰を実行できることを指摘しなければなりません。これは「末尾再帰」と呼ばれます。 Pythonは、GvRがクールではないと考えるため、末尾再帰を直接サポートしていません。
http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html
しかし、これを回避することができます:
http://paulbutler.org/archives/tail-recursion-in-python/
再帰が「間違っている」とスティックが考えるのは興味深いことです。 Schemeなどの非常に関数指向の言語では、再帰は避けられません。これにより、関数型プログラミングのパラダイムで厳密に回避されている状態変数を作成せずに反復を実行できます。
それでもsomeの範囲、つまり、中間の値を除いた最小-最大の可能な値が必要です。
まず、範囲の「半分」をランダムに選んでから、その範囲の乱数を選んでみませんか?例えば。:
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)