Reputation: 789
I am looking to generate random floats to populate a virtual reality world with objects, using the floats to define the locations of the objects. Right now it is easy to uniformly fill a "box" with objects using random.uniform call.
import random
#generate random floating coordinates
for z in range(1000):
x = random.uniform(-1,1)
y = random.uniform(-1,1)
z = random.uniform(-1,1)
#shape = vizshape.addSphere() commented out because this is an uncommon module for VR but I wanted to show how floats are being used
#shape.setPosition([x,y,z])
What I would like to do is pass in arguments to random.uniform() that specify more than 1 range to generate floats in, something like:
x = random.uniform([-1,1],[2,3])
Of course this will cause errors but I am looking for a way to get floats in multiple, size-varying, discontinuous ranges. I'd like to do it without writing another check to see if the generated floats are within my desired ranges and then deciding to keep or throw away. Any ideas?
Upvotes: 1
Views: 598
Reputation: 14858
The idea would be to first peek a range at random and then a float inside the selected range. The problem, however, is that for this to be uniform across all ranges, their length should be taken into account. Otherwise, shorter ranges would get, in the long run, the same number of samples than longer ones, which is not a uniform behavior.
In order to address this problem we can map all ranges to, say, the interval [0,1]
in such a way that relative lengths are preserved. Here is how:
[a1, b1]
, ..., [an, bn]
di = bi - ai
be the length of the i
-th rangeL
be the sum of all di
a1
to 0
and b1
to d1/L
.i >= 2
map ai
to the mapping of b_{i-1}
and bi
to that value plus di/L
.i >= 1
let xi
be the mapping of ai
.Now take a random number s
uniformly sampled in [0,1]
and proceed as follows
i0
be the last index i
such that xi <= s
.Use the inverse of the i0
-th mapping to get the answer. In other words, answer with
f = a_{i0} + (s-xi) * L / di
This number f
is in the i0
-th interval and has been chosen uniformly at random.
Upvotes: 2
Reputation: 113965
This is a bit of a hack, but it can be easily generalized to multiple discontinuous ranges:
import random
def getRandoms(n, ranges):
answer = []
for _ in xrange(n):
low,high = random.choice(ranges)
answer.append(random.uniform(low, high))
return answer
Upvotes: 1