How to randomly generate decreasing numbers in Python?

I am wondering if there is a way to generate decreasing numbers in a certain range? I want the program to keep output until it reaches 0, and the largest number in the range should be positive.

For example, if the range is (0, 100), this may be a possible output: 96 57 43 23 9 0

Sorry for the confusion from my original post.

+4
source share
8 answers

Thank you all for your answers. But I found a solution to my problem, which I thought was quite simple, and I would like to share this with all of you.

import random i = 1000000 while i > 0: i = random.randint(0, i) print i 
+1
source

I would generate a list of n random numbers, then sort them with the highest smallest.

+12
source

Little to be noted. An algorithm starting at X > 0 and at each step takes a random number from (0,X) and replaces X , and this is not good. What for? Since (provided that random behaves correctly), the expected value at each step is in the middle of the interval (0,X) . This means that the sequence of these numbers will converge to 0 up to (1/2)^N Indeed, it is easy to see that most numbers are close to 0 even for enormous value. This means that the distribution of these numbers is not uniform, which is the desired property most of the time.

This is the main drawback, although the complexity of generating the N number of O(N) and (more importantly) the use of memory is O(1) .

Another solution is to simply take the random numbers N and sort them. This is not bad, although the complexity of this algorithm is O(N log(N)) (or rather, the same as the complexity of the basic sorting algorithm), which can be reduced to O(N) if we put the elements in order instead of sorting, but memory usage is O(N) - we must remember all the elements. However, these numbers will be evenly distributed, which is a big advantage!

Following the idea in the article " Generating Sorted Lists of Random Numbers " by John Louis Bentley, here is an algorithm that is probably the most optimal one (at least that I know) and produces uniformly distributed numbers:

 import math import random def generate( min = 0, max = 10, number = 100 ): start = 0 for i in xrange( number, 0, -1 ): start = start + math.log( random.random( ) ) / i next = math.exp( start ) * ( max - min ) + min yield next for number in generate( ): print number 

Note that the complexity of this algorithm is still O(N) (which, I doubt, may be lower), but the memory usage is O(1) , and these numbers are evenly distributed in the interval (min,max) , which is not so obvious but true. The only drawback is that we need to know how many numbers we want to create before running.

Also look at this topic:

Generating sorted random numbers without sorting? O (n)

May be helpful.

+3
source

as:

 from random import random min=0 max=10 oldval=1. while True: oldval=oldval*random() randval=min+(max-min)*oldval 
+2
source

Here are a few alternatives. This should result in a chi-square distribution of values ​​with later values ​​selected from a smaller range than earlier values:

 import random random_range = range(10) numbers = [random.choice(random_range[:i]) for i in range(10, 0, -1)] 

This can also be done using float:

 import random max = 10.0 min = 0.0 desired = 100 step = (max - min) / desired numbers = [random.random() * (max - (i * step)) for i in range(desired)] 

Alternatively, selecting random values ​​from a decreasing sliding window may provide uniform distribution.

 import random, numpy max = 10.0 min = 0.0 desired = 100 step = float(min - max) / desired window = 1.0 numbers = [x + (random.random() * window) - (window / 2.0) for x in numpy.arange(max, min, step)] 

If a monotonously decreasing list of numbers is required, then setting window <= step will provide one. Good luck

+1
source

Based on the @brentlance idea, this will work for any integer range, positive, negative, or both:

 import random random_decreasing_integers_from_range = (i for i in xrange(max, min - 1, -1) if random.random() > .5) 

If you want to specify the number of outputs, try to do this to at least try to keep the range distribution somewhat homogeneous:

 import random def random_decreasing_integers_from_range(min, max, num_outputs): range_size = abs(max - min) if range_size < num_outputs: raise ValueError('Distance from min to max must be equal to or greater than num_outputs.') output_count = 0 for iteration, value in enumerate(xrange(max, min - 1, -1)): # if we only have enough values left to satisfy the number requested, # yield value if num_outputs - output_count == range_size - iteration + 1: output_count += 1 yield value # else yield value randomly, weighted by how far in to the range we are # and how many values we have left to yield of the total requested else: ratio_consumed = float(iteration + 1) / range_size ratio_yielded = float(output_count) / num_outputs if random.random() < (1 - ratio_yielded) * ratio_consumed: output_count += 1 yield value # if we've yielded the requested number of values, stop if output_count == num_outputs: break 

This works pretty well, but it seems to break when num_outputs is not between 10% and 25% of range_size. At the lower boundary, preference from the middle of the range really appears, while at the upper boundary, the short circuit condition begins to lead to the fact that the results really favor the lower end of the range.

+1
source

This will reduce random numbers in the range 0..1.

 import random def generate(): n = 1.0 while n: n = random.random() * n yield n iterator = generate() iterator.next() 

Note that the function stops giving numbers after some time, since the numbers inevitably reach 0, given the limited precision of floating point numbers.

0
source

Not an expert in python ... but here is the main idea:

 a=10000 for i in range(1,50): b=random.randint(1,a) print(b) a=b 
0
source

All Articles