生成介于0.1和1.0之间的随机数.蟒蛇

use*_*923 21 python random floating-point

我正在尝试生成介于0.1和1.0之间的随机数.我们无法使用,rand.randint因为它返回整数.我们也试过了random.uniform(0.1,1.0),但它返回的值> = 0.1且<1.0,我们不能使用它,因为我们的搜索也包含1.0.

有人对这个问题有所了解吗?

Elm*_*ise 18

你想要随机数如何"准确"?如果您对10位十进制数字感到满意,则可以舍入random.uniform(0.1, 1.0)到10位数.这样你将包括0.11.0:

round(random.uniform(0.1, 1.0), 10)
Run Code Online (Sandbox Code Playgroud)

确切地说,0.1并且1.0只有一半的概率与之间的任何其他数字相比,当然,你会丢失所有随机数,这些数字仅在10位数之后有所不同.


jfs*_*jfs 8

Random.uniform() 只是:

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()
Run Code Online (Sandbox Code Playgroud)

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

Python(以及许多其他语言)使用浮点来表示实数.如何0.1表示在文档中详细描述:

from __future__ import division

BPF = 53 # assume IEEE 754 double-precision binary floating-point format
N = BPF + 3
assert 0.1 == 7205759403792794 / 2 ** N
Run Code Online (Sandbox Code Playgroud)

它允许在不丢失精度的情况下[0.1, 1]使用(包括) 查找随机数randint():

n, m = 7205759403792794, 2 ** N
f = randint(n, m) / m
Run Code Online (Sandbox Code Playgroud)

randint(n, m)返回[n, m](包括)中的随机整数,因此上述方法可能会返回所有浮点数[0.1, 1].

另一种方法是找到最小x,从而x > 1与用途:

f = uniform(.1, x)
while f > 1:
    f = uniform(.1, x)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

两种解决方案都保持随机分布的均匀性(无歪斜).


daw*_*awg 7

你可以这样做:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

或者,使用numpy的制服:

np.random.uniform(low=0.1, high=np.nextafter(1,2), size=1)
Run Code Online (Sandbox Code Playgroud)

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


编辑

Mark Dickinson的评论似乎是正确的:Numpy的文档对于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
Run Code Online (Sandbox Code Playgroud)

在这个有限的范围内,结果也不均匀:

>>> 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
Run Code Online (Sandbox Code Playgroud)

然而,结合JF Sebastian和Mark Dickinson的评论,我认为这有效:

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)]
Run Code Online (Sandbox Code Playgroud)

如果在Mark的注释中使用最小值扩展运行,那么离散浮点值很少:

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))
Run Code Online (Sandbox Code Playgroud)

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

 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
Run Code Online (Sandbox Code Playgroud)

在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()   
Run Code Online (Sandbox Code Playgroud)

产量

制服

  • 您可能需要[我的答案中的[`while`-loop](http://stackoverflow.com/a/16301559/4279)以避免生成大于"b"的值. (2认同)