生成0.1到1.0之间的随机数。Python

2024-05-18 15:32:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图生成一个介于0.1和1.0之间的随机数。 我们不能使用rand.randint,因为它返回整数。 我们也尝试过random.uniform(0.1,1.0),但是它返回一个值>;=0.1和<;1.0,我们不能使用它,因为我们的搜索也包括1.0。

有人知道这个问题吗?


Tags: ltgt整数randomuniformrandintrand
3条回答

你想要多精确的随机数?如果你喜欢10位十进制数字,你可以把random.uniform(0.1, 1.0)四舍五入到10位。这样您将同时包含0.11.0

round(random.uniform(0.1, 1.0), 10)

准确地说,0.11.0与介于两者之间的任何其他数字相比只有一半的概率,当然,您将丢失所有仅在10位之后不同的随机数。

^{} 只是:

def uniform(self, a, b):
    "Get a random number in the range [a, b) or [a, b] depending on rounding."
    return a + (b-a) * self.random()

其中self.random()返回[0.0, 1.0)范围内的随机数。

Python(以及许多其他语言)使用floating point来表示real 数字。How ^{} is represented is described in detail in the docs

from __future__ import division

BPF = 53 # assume IEEE 754 double-precision binary floating-point format
N = BPF + 3
assert 0.1 == 7205759403792794 / 2 ** N

它允许使用 randint()不丢失精度:

n, m = 7205759403792794, 2 ** N
f = randint(n, m) / m

randint(n, m)返回[n, m](含)中的随机整数 因此,上述方法可能返回all浮点 [0.1, 1]中的数字。

另一种选择是找到最小的x,这样x > 1并使用:

f = uniform(.1, x)
while f > 1:
    f = uniform(.1, x)

x应该是最小的值,以避免丢失精度和 减少呼叫uniform()的次数,例如:

import sys
# from itertools import count

# decimal.Decimal(1).next_plus() analog
# x = next(x for i in count(1) for x in [(2**BPF + i) / 2**BPF] if x > 1)
x = 1 + sys.float_info.epsilon

这两种解都保持了随机分布(no skew)的一致性。

你可以这样做:

>>> import numpy as np
>>> a=.1
>>> b=np.nextafter(1,2)
>>> print(b)
1.0000000000000002
>>> [a+(b-a)*random.random() for i in range(10)]

或者,使用numpy's uniform

np.random.uniform(low=0.1, high=np.nextafter(1,2), size=1)

nextafter将生成特定于平台的下一个可表示的朝某个方向的浮点数。使用numpy的random.uniform是有利的,因为它不包含上界是明确的。


编辑

马克·迪金森的评论似乎是正确的:Numpy's documentation关于random.uniform是否包含上界是不正确的。

Numpy文档声明All values generated will be less than high.

这很容易被反驳:

>>> low=1.0
>>> high=1.0+2**-49
>>> a=np.random.uniform(low=low, high=high, size=10000)
>>> len(np.where(a==high)[0])
640

在这个有限的范围内,结果也不一致:

>>> for e in sorted(set(a)):
...    print('{:.16e}: {}'.format(e,len(np.where(a==e)[0])))
... 
1.0000000000000000e+00: 652
1.0000000000000002e+00: 1215
1.0000000000000004e+00: 1249
1.0000000000000007e+00: 1288
1.0000000000000009e+00: 1245
1.0000000000000011e+00: 1241
1.0000000000000013e+00: 1228
1.0000000000000016e+00: 1242
1.0000000000000018e+00: 640

然而,结合J.F.塞巴斯蒂安和马克·狄金森的评论,我认为这是可行的:

import numpy as np
import random 

def rand_range(low=0,high=1,size=1):
    a=np.nextafter(low,float('-inf'))
    b=np.nextafter(high,float('inf'))
    def r():
        def rn(): 
            return a+(b-a)*random.random()

        _rtr=rn()
        while  _rtr > high:
            _rtr=rn()
        if _rtr<low: 
            _rtr=low
        return _rtr     
    return [r() for i in range(size)]

如果以马克注释中的最小值分布运行,则离散浮点值非常少:

l,h=1,1+2**-48
s=10000
rands=rand_range(l,h,s)    
se=sorted(set(rands))
if len(se)<25:
    for i,e in enumerate(se,1):
        c=rands.count(e)
        note=''
        if e==l: note='low value end point'
        if e==h: note='high value end point'
        print ('{:>2} {:.16e} {:,}, {:.4%} {}'.format(i, e, c, c/s,note))

它产生所需的均匀分布,包括端点:

 1 1.0000000000000000e+00 589, 5.8900% low value end point
 2 1.0000000000000002e+00 544, 5.4400% 
 3 1.0000000000000004e+00 612, 6.1200% 
 4 1.0000000000000007e+00 569, 5.6900% 
 5 1.0000000000000009e+00 593, 5.9300% 
 6 1.0000000000000011e+00 580, 5.8000% 
 7 1.0000000000000013e+00 565, 5.6500% 
 8 1.0000000000000016e+00 584, 5.8400% 
 9 1.0000000000000018e+00 603, 6.0300% 
10 1.0000000000000020e+00 589, 5.8900% 
11 1.0000000000000022e+00 597, 5.9700% 
12 1.0000000000000024e+00 591, 5.9100% 
13 1.0000000000000027e+00 572, 5.7200% 
14 1.0000000000000029e+00 619, 6.1900% 
15 1.0000000000000031e+00 593, 5.9300% 
16 1.0000000000000033e+00 592, 5.9200% 
17 1.0000000000000036e+00 608, 6.0800% high value end point

在OP请求的值上,它还产生一个均匀分布:

import matplotlib.pyplot as plt

l,h=.1,1  
s=10000
bin_count=20
rands=rand_range(l,h,s)  
count, bins, ignored = plt.hist(np.array(rands),bin_count)   
plt.plot(bins, np.ones_like(bins)*s/bin_count, linewidth=2, color='r')
plt.show()   

输出

uniform

相关问题 更多 >

    热门问题