Hello all!

I am generating a random int between 0 and 75:

public static int rand(){
		int num = (int) (Math.random()*75);

		return num;
	}

How would I generate the same range of numbers but with a 70% bias for the lower half of possible numbers?

I thought I might be able to use:

Math.abs(r.nextInt()) %

but it seems this has a fatal flaw (sometimes generates negative numbers).

Any ideas? Thanks a lot!

Recommended Answers

All 4 Replies

Hello all!

I am generating a random int between 0 and 75:

public static int rand(){
		int num = (int) (Math.random()*75);

		return num;
	}

How would I generate the same range of numbers but with a 70% bias for the lower half of possible numbers?

I thought I might be able to use:

Math.abs(r.nextInt()) %

but it seems this has a fatal flaw (sometimes generates negative numbers).

Any ideas? Thanks a lot!

What about using a Bernoulli distribution with a p of 70 to generate a bool to test if I should re-generate my numbers?

You could do something like this.

pseudocode...

num = random double from 0 to 1
if (num < 0.7) num = random int from 0 to 75/2
else num = random int from 75/2-75

70% of the time it will generate a uniformly distributed random number from 0 to 75/2, the rest of the time from 75/2 to 70.

Hi all! Hope this helps - excuse the lost of formatting. Regards - John

mport java.util.*; 

// Bias Random number generator
// see static function test() for example use -

// johnny Wilson 

public class BiasRandom
{
	static Random	DEFAULTRNG	=	new Random(1235) ;

	ArrayList<Double> prob = new ArrayList<Double>();	
	double	sum				=	0  ;
	Random	random			=	new Random(1235) ;
	
	public BiasRandom()
	{
		this(BiasRandom.DEFAULTRNG) ;
	}

	// Allows you to define uniform Random number generator
	// to be used.
	
	public BiasRandom(Random rng)
	{
		random	=	rng ;
	}

	public BiasRandom(Random rng,double [] numbers)
	{
		random	=	rng ;
		defineDistArray(numbers) ;
	}
	
	public BiasRandom(double [] numbers)
	{
		this(BiasRandom.DEFAULTRNG,numbers) ;
	}
	
	
	
	public void addValue(double num)
	{
		sum	=	sum + num ;
		prob.add(new Double(num)) ;
	}
	
	public void defineDist(double... numbers)
	{
		prob 	= 	new ArrayList<Double>();	
		sum		=	0 ;
		for(double num : numbers)
		{
			addValue(num) ;
		}
	}
	
	public void defineDistArray(double[] numbers)
	{
		prob 	= 	new ArrayList<Double>();	
		sum		=	0 ;
		for (int i = 0; i < numbers.length ; i++)
		{
			addValue(numbers[i]) ;
		}
		
	}
	
	public double getSum()
	{
		return sum ;
	}
	
	// selectEvent 
	// Given a List of % probabilities of a particular event
	// Returns - a Random index - weighted by that table
	// Eg. int [] eventdistTable = {50,25,10,15}
	// Gives 10% chance of returning 0 
	// Gives 25% chance of returning 1
	// Gives 50% chance of returning 2
	// Gives 15% chance of returning 3
	
	// NB: Sum of eventdistTable elements must work out to be 100
	//  If it doesn't then % chances are worked out
	//  over the sum of elements in eventdistTable

	// Probability table is set up by the helper functions
	// defineDist(double... numbers) or defineDistArray(double[] numbers)
	// See test() for example
	
	
	public int	selectEvent()
	{
		int index 		= 0 ;
		double cummSum	= 0.0 ;
		double rnd = (double)(1 + random.nextInt((int)sum)) ;
		while(true)
		{
			cummSum = cummSum + prob.get(index) ;
			if (rnd <= cummSum) {
				return index ;
			} 
			index = index + 1 ;
		}
	}
	

	public static void test()
	{
			double []dist = {10,15,50,25} ;

			BiasRandom br 	= 	new BiasRandom() ;
			br.defineDistArray(dist) ;
			// note: above two lines can be replaced with 
			// BiasRandom br 	= 	new BiasRandom(dist) ;
			
			int [] history = new int [dist.length] ;
			int numThrows = 10000000 ;

			for (int i = 0; i < numThrows; i++)
			{
				int ev = br.selectEvent() ;
				history[ev] = history[ev] + 1 ;
			}
	
			int sum = 0 ;
			for (int i = 0; i < history.length; i++)
			{
				sum = sum + history[i] ;
				System.out.printf("Event %d percentage selected %f\n",i,(100.0 * history[i])/numThrows) ;
				
			}
			System.out.printf("Total %d\n",sum) ;
			
	}
	public static void main(String [] args)
	{
		test() ;
	}
}

Original post:
Depending on exactly how you want that distribution to go, you may be able to use a fudge like taking a random int 0-5625 then taking its square root. That will give you a smooth parabolic distribution biased towards the bottom of the range (50% of the numbers will be 0-53, and 50% 54-75. 75% of the numbers will be in the bottom 50% of the range)

Edit: Well, no, not really. That does exactly the opposite. Something like 75 - sqrt(random(5625) should be better. Anyway, it was just a thought. The nice man in the white coat is here with my medication now...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.