user1132648
user1132648

Reputation:

Generating Random Number from Histograms

I need to generate a random number from the following data:

0-10 : 23%

10-80 : 50%

80-100 : 27%

How do I generate a random number from such information?

One way would be to fit a distribution but I have to do this for about hundred variables and I don't want to fit 100 distributions. Any hints?

import random
a=[23, 73, 100]
b=[10, 80, 100]
rndval=awesomefunction(a,b)

Now, regarding awesomefunction(), I have absolutely no clue.

But, from what little I know, (and a very sloppy implementation)

temp_rand=random.uniform(0,100)
if(temp_rand<=23):
 rndval=random.uniform(0,10)
if(temp_rand<=73 && temp_rand>23):
 rndval=random.uniform(10,80)
if(temp_rand>73):
 rndval=random.uniform(80,100)

But IMHO, this is sloppy beyond measure.

Upvotes: 2

Views: 1595

Answers (4)

Paul Sasik
Paul Sasik

Reputation: 81509

C# implementation of a "ranging" random number generator with N ranges possible.

using System;
using System.Collections.Generic;

public class MyClass
{
    static void Main()
    {
        var ranges = new List<Range>
        {
            new Range( 0,  23,  0,  10),
            new Range(24,  73, 11,  80),
            new Range(74, 100, 81, 100),
        };

        for (var i = 0; i < 50; i++)
        {
            var randInt = GetRand(0, 100, ranges);
            Console.WriteLine(randInt);
        }

        Console.ReadKey();
    }

    static Random _myRandom = new Random();

    static int GetRand(int absMin, int absMax, List<Range> ranges)
    {
        var i = _myRandom.Next(absMin, absMax);

        foreach (var range in ranges)
        {
            if (i >= range.PercentMin && i <= range.PercentMax)
            {
                return _myRandom.Next(range.ValueMin, range.ValueMax);
            }
        }

        throw new ArgumentOutOfRangeException("Incomplete range?");
    }
}

class Range
{
    public int PercentMin { get; set; }
    public int PercentMax { get; set; }
    public int ValueMin { get; set; }
    public int ValueMax { get; set; }

    public Range(int pctMin, int pctMax, int min, int max)
    {
        PercentMin = pctMin;
        PercentMax = pctMax;
        ValueMin = min;
        ValueMax = max;
    }
}

Upvotes: 0

fche
fche

Reputation: 2790

See http://www.keithschwarz.com/darts-dice-coins/ and Data structure for loaded dice? for information about several approaches, trading speed and complexity.

Upvotes: 1

Paul Sasik
Paul Sasik

Reputation: 81509

You could do a two-step random fetch. The first random number would tell you which quartile (roughly) to use. Then randomly pull from that group.

Pseudocode:

randPercentile = 100 * Rand()

if (randPercentile <= 23)
    randResult = Rand(0, 23)
else if (randPercentile > 23 && randPercentile <= 73)
    randResult = Rand(24, 73)
else
    randResult = Rand(74, 100)

print randResult

You have to check the Rand API for your language/framework of choice but most Rand functions will return a float between 0 and 1 by default with overloads for minimum/maximum value ranges. And the latter call (with min/max) can be coded by you pretty easily if it's not available.

Upvotes: 0

Tanvir Ahmed
Tanvir Ahmed

Reputation: 813

You can have 2 random generators to achieve this. The first should generate a random double from 0 to 1.

For this generator, you should check to see if the random number is from 0 to .22, .23 to .73, or .74 to 1. If the number falls within the first range, you just run another random number generator that generates a number from 0 to 10, and that's your number. The same goes for the second and third ranges.

Some high level pseudocode:

double firstRandomNumber = generateRandomNumberFromZeroToOne();
if (firstRandomNumber <= .22) {
    //generate random number from 0 to 10 and that's your number.
} else if (firstRandomNumber <= .73) {
    //generate random number from 10 to 80 and that's your number.
} else {
    //generate random number from 80 to 100 and that's your number.
}

A side note: Most languages already have random number generators that will generate a random number from 0 to 1 or an integer up to a specific range (0 to 10).

Upvotes: 2

Related Questions