25

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

其他人对这个问题有想法吗?

4

10 回答 10

21

您希望随机数有多“准确”?如果您对 10 位小数感到满意,您可以四舍五入random.uniform(0.1, 1.0)到 10 位。这样,您将同时包含0.11.0

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

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

于 2013-04-29T22:01:35.613 回答
11

你可以这样做:

>>> 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 的制服

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

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

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

>>> 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

然而,结合 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)]

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

输出

制服

于 2013-04-29T22:02:05.723 回答
9

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()

whereself.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

它允许在不丢失精度的情况下在[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

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

于 2013-04-30T13:48:40.890 回答
3

With the information you've given (including comments thus far), I still fail to see how the university is going to test your program such that it will make a difference if 1.0 appears or not. (I mean, if you're required to generate random floats, how can they require that any particular value appears?)

OK, so putting the craziness of your requirements aside:

The fact that the lower bound for your random floats is higher than 0 gives you a disturbingly elegant way to use random.random, which guarantees return values in the interval [0.0, 1.0): Simply keep calling random.random, throwing away any values less than 0.1, except 0.0. If you actually get 0.0, return 1.0 instead.

So something like

from random import random

def myRandom():
    while True:
        r = random()
        if r >= 0.1:
            return r
        if r == 0.0:
            return 1.0
于 2013-04-29T22:43:41.383 回答
2

您可以通过执行以下技巧来使用 random.randint :

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

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

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

于 2013-04-29T21:53:53.760 回答
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)千分之一等等。123

于 2013-04-29T21:54:57.263 回答
1

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

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

于 2013-04-29T23:31:50.033 回答
1

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

于 2015-07-29T17:50:14.770 回答
1

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

import numpy
numpy.random.uniform(0.1, numpy.nextafter(1, 2))
于 2018-03-26T02:12:58.740 回答
0

根据 Python 3.0文档

随机的。uniform (a, b) 返回一个随机浮点数 N,使得 a <= N <= b 用于 a <= b 并且 b <= N <= a 用于 b < a。

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

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

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

随机的。uniform (a, b) 返回一个随机浮点数 N,使得 a <= N <= b 用于 a <= b 并且 b <= N <= a 用于 b < a。

取决于等式 a + (ba) * random() 中的浮点舍入,端点值 b 可能包含在范围内,也可能不包含在范围内。

于 2013-04-29T21:48:08.383 回答