python随机数范围为500输出为251_在python中生成超出范围的随机数

这在时间和内存方面提供了一种O(1)方法。

基本原理

接受的答案和其他一些答案似乎取决于生成所有可能坐标列表的必要性,或者重新计算,直到有一个可接受的解决方案。这两种方法都需要花费更多的时间和内存。

注意,根据坐标生成的一致性要求,有不同的解决方案,如下所示。

第一次尝试

随机选择右下方指定的坐标import random

# set bounding boxes

maxx=1000

maxy=800

blocked_box = [(500, 250), (100, 75)]

# generate left/right, top/bottom and choose as you like

def gen_rand_limit(p1, dim):

x1, y1 = p1

w, h = dim

x2, y2 = x1 + w, y1 + h

left = random.randrange(0, x1)

right = random.randrange(x2+1, maxx-1)

top = random.randrange(0, y1)

bottom = random.randrange(y2, maxy-1)

return random.choice([left, right]), random.choice([top, bottom])

# check boundary conditions are met

def check(x, y, p1, dim):

x1, y1 = p1

w, h = dim

x2, y2 = x1 + w, y1 + h

assert 0 <= x <= maxx, "0 <= x(%s) <= maxx(%s)" % (x, maxx)

assert x1 > x or x2 < x, "x1(%s) > x(%s) or x2(%s) < x(%s)" % (x1, x, x2, x)

assert 0 <= y <= maxy, "0 <= y(%s) <= maxy(%s)" %(y, maxy)

assert y1 > y or y2 < y, "y1(%s) > y(%s) or y2(%s) < y(%s)" % (y1, y, y2, y)

# sample

points = []

for i in xrange(1000):

x,y = gen_rand_limit(*blocked_box)

check(x, y, *blocked_box)

points.append((x,y))

结果

给定OP中概述的约束条件,这实际上会根据需要在指定矩形(红色)周围生成随机坐标(蓝色),但忽略了矩形外部但在矩形相应x或y维度内的任何有效点:

4ff8d11145c56615bdd059c5012c5f98.png

^{pr2}$

改进

这很容易通过限制x或y坐标来解决(请注意,check不再有效,请注释以运行此部分):def gen_rand_limit(p1, dim):

x1, y1 = p1

w, h = dim

x2, y2 = x1 + w, y1 + h

# should we limit x or y?

limitx = random.choice([0,1])

limity = not limitx

# generate x, y O(1)

if limitx:

left = random.randrange(0, x1)

right = random.randrange(x2+1, maxx-1)

x = random.choice([left, right])

y = random.randrange(0, maxy)

else:

x = random.randrange(0, maxx)

top = random.randrange(0, y1)

bottom = random.randrange(y2, maxy-1)

y = random.choice([top, bottom])

return x, y

624bc345809413829869b29023f9f0ad.png

调整随机偏差

正如在评论中指出的,这个解决方案存在着对矩形行/列之外的点的偏差。下面通过给每个坐标相同的概率来修正原则上的:def gen_rand_limit(p1, dim):

x1, y1 = p1Final solution -

w, h = dim

x2, y2 = x1 + w, y1 + h

# generate x, y O(1)

# --x

left = random.randrange(0, x1)

right = random.randrange(x2+1, maxx)

withinx = random.randrange(x1, x2+1)

# adjust probability of a point outside the box columns

# a point outside has probability (1/(maxx-w)) v.s. a point inside has 1/w

# the same is true for rows. adjupx/y adjust for this probability

adjpx = ((maxx - w)/w/2)

x = random.choice([left, right] * adjpx + [withinx])

# --y

top = random.randrange(0, y1)

bottom = random.randrange(y2+1, maxy)

withiny = random.randrange(y1, y2+1)

if x == left or x == right:

adjpy = ((maxy- h)/h/2)

y = random.choice([top, bottom] * adjpy + [withiny])

else:

y = random.choice([top, bottom])

return x, y

下面的图中有10000个点来说明点的统一放置(覆盖方框边界的点是由于点的大小)。

免责声明:请注意,此图将红色框置于中间位置,这样top/bottom,left/right之间的概率相同。因此,调整是相对于分块框的,而不是针对图形的所有区域。最终的解决方案需要分别调整每一个的概率。

ebadaa6f09f77b4fbabb8f2f5cbdba88.png

更简单的解决方案,但对问题稍加修改

原来,调整坐标系不同区域的概率是相当棘手的。经过一番思考,我想出了一个稍加修改的方法:

认识到在任何一个二维坐标系中,一个矩形将该区域划分为N个子区域(如果是问题,N=8),在那里可以选择一个有效的坐标。这样看,我们可以将有效的子区域定义为坐标框。然后我们可以随机选择一个长方体,并从该长方体中随机选择一个坐标:def gen_rand_limit(p1, dim):

x1, y1 = p1

w, h = dim

x2, y2 = x1 + w, y1 + h

# generate x, y O(1)

boxes = (

((0,0),(x1,y1)), ((x1,0),(x2,y1)), ((x2,0),(maxx,y1)),

((0,y1),(x1,y2)), ((x2,y1),(maxx,y2)),

((0,y2),(x1,maxy)), ((x1,y2),(x2,maxy)), ((x2,y2),(maxx,maxy)),

)

box = boxes[random.randrange(len(boxes))]

x = random.randrange(box[0][0], box[1][0])

y = random.randrange(box[0][1], box[1][1])

return x, y

注意这并不是一般化的,因为阻塞的框可能不在中间,因此boxes看起来会不同。因此,在每个框中以相同的概率选择,我们得到每个框中相同的点数。很明显,小盒子里的密度更高:

2bb07cde33b123b5e5d241d00e8564aa.png

如果要求在所有可能的坐标系中生成均匀分布,则解决方案是计算boxes,使每个方框的大小与阻塞框的大小相同。基督教青年会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值