特定の範囲内で減少する数を生成する方法があるかどうか疑問に思っていますか?0に達するまで出力を続けるようにプログラムしたいのですが、範囲内の最大数は正でなければなりません。
たとえば、範囲が(0、100)の場合、これは次の出力の可能性があります。96 57 43 23 9 0
私の元の投稿からの混乱をお詫びします
特定の範囲内で減少する数を生成する方法があるかどうか疑問に思っていますか?0に達するまで出力を続けるようにプログラムしたいのですが、範囲内の最大数は正でなければなりません。
たとえば、範囲が(0、100)の場合、これは次の出力の可能性があります。96 57 43 23 9 0
私の元の投稿からの混乱をお詫びします
n個の乱数のリストを生成し、それらを最高から最低に並べ替えます。
注意する必要のあることはほとんどありません。X > 0
各ステップで開始し、各ステップで乱数を取得して(0,X)
置き換えるアルゴリズムX
は適切ではありません。なんで?なぜなら(random
正しく動作すると仮定して)各ステップの期待値は間隔の真ん中にあるから(0,X)
です。これは、これらの数のシーケンスがと0
同じくらい速く収束すると予想されることを意味し(1/2)^N
ます。0
そして確かに、莫大な初期値であっても、数字の大部分が近くにあることが簡単にわかります。これは、これらの数値の分布が均一ではないことを意味します。これは、ほとんどの場合、望ましい特性です。
これは大きな欠点ですが、N
数を生成することの複雑さはでO(N)
あり、(より重要なことは)メモリ使用量はO(1)
です。
もう1つの解決策は、N
乱数を取得して並べ替えることです。これは悪いことではありませんが、このアルゴリズムの複雑さはO(N log(N))
(または基礎となる並べ替えアルゴリズムの複雑さと同じです)、O(N)
並べ替えの代わりに要素を並べ替えると減らすことができますが、メモリ使用量はO(N)
すべて覚えておく必要があります要素。ただし、これらの数値は均一に分散されるため、大きな利点があります。
Jon Louis Bentleyによる論文「乱数のソートされたリストの生成」のアイデアに従って、これがおそらく最も最適なアルゴリズムであり(少なくとも私には知られています)、均一に分散された数を生成します。
import math
import random
def generate( min = 0, max = 10, number = 100 ):
start = 0
for i in xrange( number, 0, -1 ):
start = start + math.log( random.random( ) ) / i
next = math.exp( start ) * ( max - min ) + min
yield next
for number in generate( ):
print number
このアルゴリズムの複雑さはまだO(N)
(私は低くなる可能性があるとは思えませんが)ですが、メモリ使用量はそうO(1)
であり、これらの数値は間隔(min,max)
で均一に分散されていることに注意してください。これはそれほど明白ではありませんが、真実です。唯一の欠点は、開始する前に、生成する数値の数を知る必要があることです。
このスレッドもご覧ください。
ソートせずにソートされたランダムintを生成しますか?の上)
役に立つかもしれません。
お気に入り:
from random import random
min=0
max=10
oldval=1.
while True:
oldval=oldval*random()
randval=min+(max-min)*oldval
ここにいくつかの選択肢があります。これにより、値のカイ2乗分布に近くなり、後の値が前の値よりも狭い範囲から選択されます。
import random
random_range = range(10)
numbers = [random.choice(random_range[:i]) for i in range(10, 0, -1)]
これはフロートでも実行できます。
import random
max = 10.0
min = 0.0
desired = 100
step = (max - min) / desired
numbers = [random.random() * (max - (i * step)) for i in range(desired)]
あるいは、減少するスライディングウィンドウからランダムな値を選択すると、均一な分布を提供できます。
import random, numpy
max = 10.0
min = 0.0
desired = 100
step = float(min - max) / desired
window = 1.0
numbers = [x + (random.random() * window) - (window / 2.0) for x in numpy.arange(max, min, step)]
単調に減少する数のリストが必要な場合は、設定window <= step
によって1つ提供されます。幸運を!
@brentlanceのアイデアに基づいて、これは任意の整数範囲、正、負、またはその両方で機能します。
import random
random_decreasing_integers_from_range = (i for i in xrange(max, min - 1, -1) if random.random() > .5)
出力の数を指定できるようにしたい場合は、少なくとも範囲全体の分布をある程度均一に保とうとする試みを次に示します。
import random
def random_decreasing_integers_from_range(min, max, num_outputs):
range_size = abs(max - min)
if range_size < num_outputs:
raise ValueError('Distance from min to max must be equal to or greater than num_outputs.')
output_count = 0
for iteration, value in enumerate(xrange(max, min - 1, -1)):
# if we only have enough values left to satisfy the number requested,
# yield value
if num_outputs - output_count == range_size - iteration + 1:
output_count += 1
yield value
# else yield value randomly, weighted by how far in to the range we are
# and how many values we have left to yield of the total requested
else:
ratio_consumed = float(iteration + 1) / range_size
ratio_yielded = float(output_count) / num_outputs
if random.random() < (1 - ratio_yielded) * ratio_consumed:
output_count += 1
yield value
# if we've yielded the requested number of values, stop
if output_count == num_outputs:
break
これはかなりうまく機能しますが、num_outputsがrange_sizeの約10%から25%の間にない場合、機能しなくなるようです。下限では、範囲の中央を優先することが実際に透けて見えますが、上限では、短絡状態により、結果が範囲の下限を実際に優先するようになります。
みなさん、ありがとうございました。しかし、私は自分の問題の解決策を見つけました。それは非常に簡単だと思いました。それを皆さんと共有したいと思います。
import random
i = 1000000
while i > 0:
i = random.randint(0, i)
print i
これにより、0..1の範囲で乱数が減少します。
import random
def generate():
n = 1.0
while n:
n = random.random() * n
yield n
iterator = generate()
iterator.next()
浮動小数点数の精度が限られているため、数値は必然的に0に達するため、関数はしばらくすると数値の生成を停止することに注意してください。
Pythonの専門家ではありません...しかし、これが私が持っている基本的な考え方です:
a=10000
for i in range(1,50):
b=random.randint(1,a)
print(b)
a=b