views:

324

answers:

8

when you use the random(min,max) function in most languages, what is the distribution like ?

what if i want to produce a range of numbers for 20% of the time, and another range of numbers for 80% of the time, how can i generate series of random number that follows that ?

ex) i should get random frequency but the frequency of "1" must be higher by around 20% than the frequency of "0"

A: 

Most computer languages have a uniform distribution to their (pseudo) random integer generators. So each integer is equally likely.

For your example, suppose you want "1" 55% of the time and "0" 45% of the time.

To get unequal these frequencies, try generating a random number between 1 and 100. If the number generated is from 1 to 55, output "1"; otherwise output "0".

Peter K.
PS: a "normal" distribution is NOT the same thing as a uniform distribution.
Peter K.
+1  A: 

Most pseudo random generators built-in programming languages produce a uniform distribution, i.e. each value within the range has the same probability of being produced as any other value in the range. Indeed in some cases this requirement is part of the language standard. Some languages such as Python or R support various of the common distributions.

If the language doesn't support it, you either have to use mathematical tricks to produce other distributions such as a normal distribution from a uniform one, or you can look for third-party libraries which perform this function.

Your problem seems much simpler however since the random variable is discrete (and of the simpler type thereof, i.e binary). The trick for these is to produce a random number form the uniform distribution, in a given range, say 0 to 999, and to split this range in the proportions associated with each value, in the case at hand this would be something like :

  If (RandomNumber) < 200    // 20%
     RandomVariable = 0
  Else                       // 80%
     RandomVariable = 1

This logic can of course be applied to n discrete variables.

mjv
A: 

For most languages, the random number generated can be dependent on an algorithm within that language, or generated randomly based on the several factors such as time, processor, seed number.

The distribution is not normal. In fact say if the function returns 5 integers, all 5 integers have a fair chance of appearing in the next function call. This is also known as uniformed distribution.

So say if you wish to produce a number (say 7) for 20% of the time, and another number (say 13) for 80% of the time, you can do an array like this:

var arr = [7,13,13,13,13];
var picked = arr[Math.floor(Math.random()*arr.length)] ; 
// since Math.random() returns a float from 0.0 to 1.0

So thus 7 has a 20% chance of appearing, and 13 has 80% chance.

thephpdeveloper
+1  A: 

This is one possible method:

ranges = [(10..15), (20..30)]
selector = [0, 0, 1,1,1,1,1,1,1,1] # 80:20 distribution array

# now select a range randomly    
random_within_range(ranges(selector[random(10)]))  


def random_within_range range
  rand (range.last - range.begin - (range.exclude_end? ? 1 : 0)) + range.begin
end
KandadaBoggu
A: 

How about

var oneFreq = 80.0/100.0;
var output = 0;
if (Math.random() > oneFreq)
   output = 1;

or, if you want 20% of the values to be between 0 and 100, and 80% to be between 100 and 200.

var oneFreq = 80.0/100.0;
var oneRange  = 100;
var zeroRange = 100;
var output = Math.random();
if (output > oneFreq)
   output = zeroRange + Math.floor(oneRange * (output - oneFreq));
else
   output = Math.floor(zeroRange * output);
John Knoeller
+1  A: 

Your question differs from your example quite a bit. So I'll answer both and you can figure out whichever answers what you're really looking for.

1) Your example (I don't know ruby or java, so bear with me)

  • First generate a random number from a uniform distribution from 0 to 1, we'll call it X.
  • You can then setup a if/else (i.e. if ( x < .2) {1} else {0})

2) Generating random numbers from a normal distribution with skew

  • You can look into skewed distributions such as a skewed student T's distribution with high degree of freedom.
  • You can also use the normal CDF and just pick off numbers that way.
  • Here's a paper which discusses how to do it with multiple random numbers from a uniform distribution
  • Finally, you can use a non-parametric approach which would involve kernal density estimation (I suspect you aren't looking for anything this sophisticated however).
ast4
A: 

Have a look at this lecture if you want a good mathematical understanding.

zdav
A: 

In ruby I would do it like this:

class DistributedRandom
  def initialize(left, right = nil)
    if right
      @distribution = [0] * left + [1] * right
    else
      @distribution = left
    end
  end
  def get
    @distribution[rand @distribution.length]
  end
end

Running a test with 80:20 distribution:

test = [0,0]
rnd = DistributedRandom.new 80, 20   # 80:20 distribution
10000.times { test[rnd.get] += 1 }; puts "Test 1", test

Running a test with 20% more distribution on the right side:

test = [0,0]
rnd = DistributedRandom.new 100, 120   # +20% distribution
10000.times { test[rnd.get] += 1 }; puts "Test 2", test

Running a test with custom distribution with a trigonometric function over 91 discrete values, output however does not fit very well into the previous tests:

test = [0,0]
rnd = DistributedRandom.new((0..90).map {|x| Math.sin(Math::PI * x / 180.0)})
10000.times { test[rnd.get] += 1 }; puts "Test 3", test
hurikhan77