Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Generate a sequence of random numbers that sum up to 1?

Reply
Thread Tools

Generate a sequence of random numbers that sum up to 1?

 
 
Anthony Liu
Guest
Posts: n/a
 
      04-22-2006
I am at my wit's end.

I want to generate a certain number of random numbers.
This is easy, I can repeatedly do uniform(0, 1) for
example.

But, I want the random numbers just generated sum up
to 1 .

I am not sure how to do this. Any idea? Thanks.

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
 
Reply With Quote
 
 
 
 
Mel Wilson
Guest
Posts: n/a
 
      04-22-2006
Anthony Liu wrote:
> I am at my wit's end.
>
> I want to generate a certain number of random numbers.
> This is easy, I can repeatedly do uniform(0, 1) for
> example.
>
> But, I want the random numbers just generated sum up
> to 1 .
>
> I am not sure how to do this. Any idea? Thanks.


numbers.append (random.uniform (0, 1.0-sum(numbers)))

might help, perhaps.

or

scaled = [x/sum(numbers) for x in numbers]

Mel.
>

 
Reply With Quote
 
 
 
 
Edward Elliott
Guest
Posts: n/a
 
      04-22-2006
Anthony Liu wrote:
> But, I want the random numbers just generated sum up
> to 1 .


This seems like an odd request. Might I ask what it's for?

Generating random numbers in [0,1) that are both uniform and sum to 1 looks
like an unsatisfiable task. Each number you generate restricts the
possibilities for future numbers. E.g. if the first number is 0.5, all
future numbers must be < 0.5 (indeed, must *sum* to 0.5). You'll end up
with a distribution increasingly skewed towards smaller numbers the more
you generate. I can't imagine what that would be useful for.

If that's not a problem, do this: generate the numbers, add them up, and
divide each by the sum.

nums = [random.uniform(0,1) for x in range(0,100)]
sum = reduce(lambda x,y: x+y, nums)
norm = [x/sum for x in nums]

Of course now the numbers aren't uniform over [0,1) anymore.

Also note that the sum of the normalized numbers will be very close to 1,
but slightly off due to representation issues. If that level of accuracy
matters, you might consider generating your rands as integers and then
fp-dividing by the sum (or just store them as integers/fractions).
 
Reply With Quote
 
Felipe Almeida Lessa
Guest
Posts: n/a
 
      04-22-2006
Em Sáb, 2006-04-22 *s 03:16 +0000, Edward Elliott escreveu:
> If that level of accuracy
> matters, you might consider generating your rands as integers and then
> fp-dividing by the sum (or just store them as integers/fractions).


Or using decimal module: http://docs.python.org/lib/module-decimal.html

--
Felipe.

 
Reply With Quote
 
Alex Martelli
Guest
Posts: n/a
 
      04-22-2006
Anthony Liu <(E-Mail Removed)> wrote:
...
> As a matter of fact, given that we have to specify the
> number of states for an HMM, I would like to create a
> specified number of random floating numbers whose sum
> is 1.0.


def forAL(N):
N_randoms = [random.random() for x in xrange(N)]
total = sum(N_randoms)
return [x/total for x in N_randoms]


Does this do what you want? Of course, the resulting numbers are not
independent, but then the constraints you pose would contradict that.


Alex
 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      04-22-2006

Anthony Liu wrote:
> I am at my wit's end.
>
> I want to generate a certain number of random numbers.
> This is easy, I can repeatedly do uniform(0, 1) for
> example.
>
> But, I want the random numbers just generated sum up
> to 1 .
>
> I am not sure how to do this. Any idea? Thanks.
>


--------------------------------------------------------------
import random

def partition(start=0,stop=1,eps=5):
d = stop - start
vals = [ start + d * random.random() for _ in range(2*eps) ]
vals = [start] + vals + [stop]
vals.sort()
return vals

P = partition()

intervals = [ P[i:i+2] for i in range(len(P)-1) ]

deltas = [ x[1] - x[0] for x in intervals ]

print deltas

print sum(deltas)
---------------------------------------------------------------

Gerard

 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      04-22-2006

Gerard Flanagan wrote:
> Anthony Liu wrote:
> > I am at my wit's end.
> >
> > I want to generate a certain number of random numbers.
> > This is easy, I can repeatedly do uniform(0, 1) for
> > example.
> >
> > But, I want the random numbers just generated sum up
> > to 1 .
> >
> > I am not sure how to do this. Any idea? Thanks.
> >

>
> --------------------------------------------------------------
> import random
>
> def partition(start=0,stop=1,eps=5):
> d = stop - start
> vals = [ start + d * random.random() for _ in range(2*eps) ]
> vals = [start] + vals + [stop]
> vals.sort()
> return vals
>
> P = partition()
>
> intervals = [ P[i:i+2] for i in range(len(P)-1) ]
>
> deltas = [ x[1] - x[0] for x in intervals ]
>
> print deltas
>
> print sum(deltas)
> ---------------------------------------------------------------
>


def partition(N=5):
vals = sorted( random.random() for _ in range(2*N) )
vals = [0] + vals + [1]
for j in range(2*N+1):
yield vals[j:j+2]

deltas = [ x[1]-x[0] for x in partition() ]

print deltas

print sum(deltas)

>>>

[0.10271966686994982, 0.13826576491042208, 0.064146913555132801,
0.11906452454467387, 0.10501198456091299, 0.011732423830768779,
0.11785369256442912, 0.065927165520102249, 0.098351305878176198,
0.077786747076205365, 0.099139810689226726]
1.0

 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      04-22-2006
Gerard Flanagan wrote:
> Gerard Flanagan wrote:
> > Anthony Liu wrote:
> > > I am at my wit's end.
> > >
> > > I want to generate a certain number of random numbers.
> > > This is easy, I can repeatedly do uniform(0, 1) for
> > > example.
> > >
> > > But, I want the random numbers just generated sum up
> > > to 1 .
> > >
> > > I am not sure how to do this. Any idea? Thanks.
> > >

> >
> > --------------------------------------------------------------
> > import random
> >
> > def partition(start=0,stop=1,eps=5):
> > d = stop - start
> > vals = [ start + d * random.random() for _ in range(2*eps) ]
> > vals = [start] + vals + [stop]
> > vals.sort()
> > return vals
> >
> > P = partition()
> >
> > intervals = [ P[i:i+2] for i in range(len(P)-1) ]
> >
> > deltas = [ x[1] - x[0] for x in intervals ]
> >
> > print deltas
> >
> > print sum(deltas)
> > ---------------------------------------------------------------
> >

>
> def partition(N=5):
> vals = sorted( random.random() for _ in range(2*N) )
> vals = [0] + vals + [1]
> for j in range(2*N+1):
> yield vals[j:j+2]
>
> deltas = [ x[1]-x[0] for x in partition() ]
>
> print deltas
>
> print sum(deltas)
>


finally:

---------------------------------------------------------------
def distribution(N=2):
p = [0] + sorted( random.random() for _ in range(N-1) ) + [1]
for j in range(N):
yield p[j+1] - p[j]

spread = list(distribution(10))

print spread
print sum(spread)
---------------------------------------------------------------
Gerard

 
Reply With Quote
 
Nick Craig-Wood
Guest
Posts: n/a
 
      04-23-2006
Gerard Flanagan <(E-Mail Removed)> wrote:
> def distribution(N=2):
> p = [0] + sorted( random.random() for _ in range(N-1) ) + [1]
> for j in range(N):
> yield p[j+1] - p[j]
>
> spread = list(distribution(10))
>
> print spread
> print sum(spread)


This is simpler, easier to prove correct and most likely quicker.

def distribution(N=2):
L = [ random.uniform(0,1) for _ in xrange(N) ]
sumL = sum(L)
return [ l/sumL for l in L ]

spread = distribution(10)
print spread
print sum(spread)

--
Nick Craig-Wood <(E-Mail Removed)> -- http://www.craig-wood.com/nick
 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      04-23-2006
Nick Craig-Wood wrote:
> Gerard Flanagan <(E-Mail Removed)> wrote:
> > def distribution(N=2):
> > p = [0] + sorted( random.random() for _ in range(N-1) ) + [1]
> > for j in range(N):
> > yield p[j+1] - p[j]
> >
> > spread = list(distribution(10))
> >
> > print spread
> > print sum(spread)

>
> This is simpler, easier to prove correct and most likely quicker.
>
> def distribution(N=2):
> L = [ random.uniform(0,1) for _ in xrange(N) ]
> sumL = sum(L)
> return [ l/sumL for l in L ]
>


simpler:- ok

easier to prove correct:- in what sense?

quicker:- slightly slower in fact (using xrange in both functions).
This must be due to 'uniform' - using random() rather than uniform(0,1)
then yes, it's quicker. Roughly tested, I get yours (and Alex
Martelli's) to be about twice as fast. (2<=N<1000, probably greater
difference as N increases).

All the best.

Gerard

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
problem in running a basic code in python 3.3.0 that includes HTML file Satabdi Mukherjee Python 1 04-04-2013 07:48 PM
gen n random numbers sum to 1 Prakhar C++ 3 06-12-2007 04:37 PM
Re: Generate a sequence of random numbers that sum up to 1? Anthony Liu Python 1 04-29-2006 11:36 PM
Re: Generate a sequence of random numbers that sum up to 1? Anthony Liu Python 0 04-22-2006 08:10 PM
How do make a function that creates a sequence of n random numbers? shivermetimbers15 Python 12 02-18-2004 10:27 PM



Advertisments