我正在尝试生成介于0.1和1.0之间的随机数。
我们不能使用rand.randint
因为它返回整数。
我们还尝试了random.uniform(0.1,1.0)
,但它返回的值> = 0.1且< 1.0,我们不能使用它,因为我们的搜索也包括1.0。
其他人是否对这个问题有所了解?
答案 0 :(得分:18)
您想要随机数字的“准确度”如何?如果您对10位十进制数字感到满意,则可以将random.uniform(0.1, 1.0)
舍入为10位数。这样您就可以同时包含0.1
和1.0
:
round(random.uniform(0.1, 1.0), 10)
准确地说,0.1
和1.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()
输出
答案 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.1
(random.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))