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

时间:2013-04-29 21:43:18

标签: python random floating-point

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

其他人是否对这个问题有所了解?

10 个答案:

答案 0 :(得分:18)

您想要随机数字的“准确度”如何?如果您对10位十进制数字感到满意,则可以将random.uniform(0.1, 1.0)舍入为10位数。这样您就可以同时包含0.11.0

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

准确地说,0.11.0只有一半的概率与之间的任何其他数字相比,当然,你会丢失所有仅在10位数之后不同的随机数。< / p>

答案 1 :(得分: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()

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

Python(以及许多其他语言)使用floating point来表示真实 数字。 How 0.1 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

它允许使用[0.1, 1](包括)查找随机数 randint()而不会失去精确度:

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

randint(n, m)返回[n, m](包括)中的随机整数 因此,上述方法可能会返回所有浮点数 [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)。

答案 2 :(得分: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)]

或,使用numpy's uniform

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

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


编辑

看来Mark Dickinson的评论是正确的: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. 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)]

如果在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))

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

 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

答案 3 :(得分:3)

根据您提供的信息(包括迄今为止的评论),我仍然无法看到大学将如何测试您的程序,以便在1.0出现与否时会产生影响。 (我的意思是,如果您需要生成随机浮点数,他们怎么能要求出现任何特定值?)

好的,所以把你的要求的疯狂放在一边:

随机浮点数的下限高于0的事实为您提供了一种令人不安的优雅方式来使用random.random,这保证了区间[0.0,1.0]中的返回值:只需保持调用{{1扔掉任何小于0.1的值,除了0.0。如果实际得到0.0,则返回1.0。

类似

random.random

答案 4 :(得分:2)

你可以通过这个技巧简单地使用random.randint:

>>> float(random.randint(1000,10000)) / 10000
0.4362

如果您想要更多小数,只需将间隔更改为:

(1000,10000)4位数 (10000,100000)5位数 等

答案 5 :(得分:1)

您无法使用random.random()吗?这给出了一个介于0.0和1.0之间的数字,尽管你可以轻松地设置一种方法来解决这个问题。

import random
def randomForMe():
    number = random.random()
    number = round(number, 1)
    if (number == 0):
        number = 0.1

此代码会为您提供介于0.1和1.0之间的数字(0.1和1.0都是可能的解决方案)。希望这会有所帮助。

*我以为你只想要数字到十分之一。如果您希望它与众不同,我输入round(number, 1)的位置会将1更改为2百分之一,3更改为千分之一,依此类推。

答案 6 :(得分:1)

标准方式是random.random() * 0.9 + 0.1random.uniform()内部就是这样)。这将返回0.1到1.0之间没有上边框的数字。

但是等等! 0.1(又名¹/ 10)没有明确的二进制表示(十进制为⅓)!因此,无论如何你都不会得到真正的0.1,因为计算机无法在内部表示它。对不起; - )

答案 7 :(得分:0)

根据Python 3.0 documentation

  

随机。均匀(a,b)返回随机浮点数N,使得&lt; = N&lt; = b&lt; = b且b&lt; = N&lt; = a对于b&lt;一个。

因此,random.uniform()实际上包括上限,至少在Python 3.0上。

编辑:正如@Blender所指出的,Python 3.0的文档似乎与此处的源代码不一致。

编辑2:正如@MarkDickinson指出的那样,我无意中链接到Python 3.0文档而不是最新的Python 3文档here,其内容如下:

  

随机。统一(a,b)返回随机浮点数N等   a&lt; = N&lt; = b&lt; = b且b&lt; = N&lt; = a代表b&lt;一个。

     

终点   值b可能包括也可能不包括在范围内,具体取决于   方程a +(b-a)* random()中的浮点舍入。

答案 8 :(得分:0)

尝试     random.randint(1,10)/100.0

答案 9 :(得分:0)

在numpy中,您可以执行以下操作:

import numpy
numpy.random.uniform(0.1, numpy.nextafter(1, 2))