random.uniform(0,1)は0または1を生成できますか?


9

ではドキュメントチャンスがあると言われているuniform(0,1)値を生成することができます0し、で1

私はuniform(0, 1)10000回実行しましたが、ゼロを生成したことはありません。の場合でもuniform(0, 0.001)

random.uniform(0,1)これまでに生成できます01


3
理論的には可能ですが、実際には起こりません。数学的には、標準の一様確率変数は、0〜1の範囲の任意の値をとることができます。の場合X ~ U(0,1)、xのすべての値について、P(X=x)ほぼ確実に 0です。(間隔で無限に多くの可能な値があるためです。)あなたは正確に0または1を探しているなら、あなたは、例えば、異なる機能-使用する必要がありますrandom.choice
pault

1
@pault は数学でほぼ確実に非常に特定の意味を持っています。連続間隔ではなく離散分布があるため、ここでは実際には意味がありません。0と1の間の浮動小数点数の唯一の有限数がある
WIM

2
@paultでは、なぜOPがの実装について尋ねているときに数学的に話すのrandom.uniformですか?
WIM

1
そのドキュメントが正確である場合 0と1の両方を生成する方法について興味があります。[0、1)のようにはるかに簡単です(Math.random()たとえば、JavaScriptでどのように機能するか)。
Ry-

1
random.uniform(0, 1)最初の呼び出しで最初に0 を返すランダムシードを投稿する最初の人に50ポイントの賞金
wim

回答:


13

uniform(0, 1)は生産でき0ますが、生産されることはありません1

ドキュメントには、エンドポイントがあることがわかりますb 可能性が生成された値に含まれます。

b式の浮動小数点の丸めに応じて、終点の値が範囲に含まれる場合と含まれない場合がありますa + (b-a) * random()

したがってuniform(0, 1)、の式は0 + (1-0) * random()、に簡略化され1 * random()1正確に生成できる必要があります。それrandom.random()は1.0 exactly. However,random()*never* produces1.0`の場合にのみ発生します。

random.random()ドキュメントの引用:

[0.0、1.0)の範囲の次のランダムな浮動小数点数を返します。

表記[..., ...)は、最初の値がすべての可能な値の一部であることを意味しますが、2番目の値はそうではありません。random.random()ほとんどの農産物値で意志非常に近く1.0。Pythonのfloatタイプは、IEEE 754 base64浮動小数点値であり、を構成する2進分数(1 / 2、1 / 4、1 / 5など)をエンコードします。値がrandom.random()生成するのは、単に2 ** -1(1/2)から2 ** -53(1/9007199254740992)までの53のそのようなフラクションのランダムな選択。

ただし、に非常に近い値生成される可能性があるため1.0、浮動小数点ナブマーを乗算したときに発生する丸め誤差とともに、およびの一部の値に対して生成できます。しかし、これらの価値観には含まれていません。bab01

は0.0 random.random() 生成できるためarandom.uniform()a + (b - a) * 0 == a)の可能な値に常に含まれていることに注意してください。生成さ2 ** 53れるrandom.random()可能性のあるさまざまな値(53の2進数のすべての可能な組み合わせ)があるため、これが発生する可能性は2 ** 531インチ(9007199254740992に1倍)です。

したがって、random.random()生成できる最大値は1 - (2 ** -53)です。十分に小さい値を選択するだけでb - a、より高いrandom.random()値を掛けたときに丸めが有効になります。小さいほどb - a、それが発生する可能性が高くなります。

>>> import random, sys
>>> def find_b():
...     a, b = 0, sys.float_info.epsilon
...     while random.uniform(a, b) != b:
...         b /= 2
...     else:
...         return b
...
>>> print("uniform(0, {0}) == {0}".format(find_b()))
...
uniform(0, 4e-323) == 4e-323

b = 0.0押すと、1023回の除算が行われます。上記の値は、1019回の除算でラッキーになったことを意味します。私がこれまでに見つけた最高の値(上記の関数をループで実行max())は8.095e-320(1008目盛)ですが、おそらくもっと高い値があります。それはすべて偶然のゲームです。:-)

それはまたの間にはない多くの離散的なステップがある場合に発生する可能性がありますab、ときのようにaしてb高い指数を持っており、これまでのところ、アパートのように見えることがあります。浮動小数点値はまだ近似値に過ぎず、エンコードできる値の数は有限です。例えば、差のわずか1バイナリ画分が存在するsys.float_info.maxsys.float_info.max - (2 ** 970)、そう50-50可能性があるrandom.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)作り出しますsys.float_info.max

>>> a, b = sys.float_info.max - (2 ** 970), sys.float_info.max
>>> values = [random.uniform(a, b) for _ in range(10000)]
>>> values.count(sys.float_info.max)  # should be roughly 5000
4997

5

「数回」では十分ではありません。10,000では十分ではありません。random.uniform2 ^ 53(9,007,199,254,740,992)の異なる値から選択します。そのうちの2つに興味があります。そのため、正確に0または1の値を取得する前に、数兆のランダムな値を生成することを期待する必要があります。したがって、それは可能ですが、それを決して観察しない可能性が非常に高くなります。


2
以下のために不可能生産するために、結果として。これは、関数がとして定義されており、を生成できないためです。uniform(0, 1)1def uniform(a, b): return a + (b - a) * random()random()1.0
Martijn Pieters

2
@MartijnPieters私はあなたが正しいと信じており、私はあなたの答えを支持しました。私は同じくらい疑ったが、確信が持てず、それは私の答えの主な目的とは別だったので、私はそれを次のようにさせた:)
ホッブズ

1

正確な0を表示するために必要な反復回数をカウントするループを試して生成できます(しないでください)。

さらに、ホッブズが述べたように、uniformlyサンプリングされる値の量は9,007,199,254,740,992です。つまり、0が表示される確率は正確に1 / 9,007,199,254,740,992です。これは、一般的に言えば、切り上げにより、0を見つけるために平均 10兆兆個のサンプルが必要になることを意味します。もちろん、最初の10回の試行でそれが見つかるかもしれません。

値に定義された間隔は括弧で閉じられているため、1を含まないため、1をサンプリングすることは不可能です。


1

承知しました。uniform(0, 0.001)代わりに試すことで、あなたはすでに正しい方向に進んでいた。境界を制限し続けて、それがより早く発生するようにします。

>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
0.0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.