ドキュメント では、uniform(0,1)
が_0
_および_1
_の値を生成できる可能性があると言われています。
uniform(0, 1)
を10000回実行しましたが、ゼロは生成されませんでした。 uniform(0, 0.001)
の場合でも同様です。
random.uniform(0,1)
は_0
_または_1
_を生成できますか?
uniform(0, 1)
は_0
_を生成できますが、neverは_1
_を生成します。
documentation は、エンドポイントb
couldが生成された値に含まれることを示しています。
エンドポイント値
b
は、式a + (b-a) * random()
の浮動小数点の丸めに応じて、範囲に含まれる場合と含まれない場合があります。
したがって、uniform(0, 1)
の場合、0 + (1-0) * random()
に簡略化された式1 * random()
は、_1
_を正確に生成できる必要があります。これは、random.random()
が1.0 _exactly. However,
_ random()_*never* produces
_ 1.0`の場合にのみ発生します。
[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
_に非常に近い値を生成する可能性があるため、浮動小数点ナブマーを乗算するときに発生する丸めエラーとともに、canはsome値に対してb
を生成しますa
およびb
のただし、_0
_および_1
_はこれらの値には含まれません。
random.random()
canは0.0を生成するため、a
は常にrandom.uniform()
(a + (b - a) * 0 == a
)の可能な値に含まれることに注意してください。 random.random()
が生成できる_2 ** 53
_異なる値(53の2進数のすべての可能な組み合わせ)があるため、その可能性は_2 ** 53
_に1つ(つまり、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目盛)ですが、おそらくそれより高い値があります。それはすべて偶然のゲームです。 :-)
また、a
とb
の指数が高く、かなり離れているように見える場合など、a
とb
の間に個別のステップがあまりない場合にも発生します。浮動小数点値はまだ近似値に過ぎず、エンコードできる値の数は有限です。たとえば、_sys.float_info.max
_とsys.float_info.max - (2 ** 970)
の違いは2進数の1つしかないため、random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
が_sys.float_info.max
_を生成する可能性は50〜50です。
_>>> 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
_
「数回」では十分ではありません。 10,000では十分ではありません。 random.uniform
は、2 ^ 53(9,007,199,254,740,992)の異なる値から選択します。あなたはそれらのtwoに興味があります。そのため、正確に0または1の値を取得する前に、いくつかのquadrillionランダムな値を生成することを期待する必要があります。したがって、それは可能ですが、決して観察しない可能性が非常に高いです。
承知しました。代わりに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
正確な0を表示するために必要な反復回数をカウントするループを試して生成できます(しないでください)。
さらに、Hobbsが述べたように、uniformly
でサンプリングされる値の量は9,007,199,254,740,992です。つまり、0が表示される確率は正確に1/9,007,199,254,740,992です。これは、一般的に言えば、切り上げはaverage 10兆サンプルで0を見つける必要があることを意味します。もちろん、あなたの最初の10回の試みでそれを見つけてください。
値に定義された間隔は括弧で閉じられているため、1を含まないため、1をサンプリングすることは不可能です。