Chanon
Chanon

Reputation: 41

Generate a random number with max, min and mean (average) in Matlab

I need to generate random numbers with following properties.

I have tried several syntaxes but nothing works, for example

r=1+8.*rand(100,1);

This gives me a random number between 1-9 but it's not an integer (for example 5.607 or 4.391) and each time I calculate the mean it varies.

Upvotes: 3

Views: 8860

Answers (6)

lsfinn
lsfinn

Reputation: 446

Before you can design your random number generator you need to specify the distribution it should draw from. You've only partially done that: i.e., you specified it draws from integers in [1,9] and that it has a mean that you want to be able to specify. That still leaves an infinity of distributions to chose among. What other properties do you want your distribution to have?

Edit following comment: The mean of any finite sample from a probability distribution - the so-called sample mean - will only approximate the distribution's mean. There is no way around that.

That having been said, the simplest (in the maximum entropy sense) distribution over the integers in the domain [1,9] is the exponential distribution: i.e.,

p = @(n,x)(exp(-x*n)./sum(exp(-x*(1:9))));

The parameter x determines the distribution mean. The corresponding cumulative distribution is

c = cumsum(p(1:9,x));

To draw from the distribution p you can draw a random number from [0,1] and find what sub-interval of c it falls in: i.e.,

samp = arrayfun(@(y)find(y<c,1),rand(n,m));

will return an [n,m] array of integers drawn from p.

Upvotes: 1

yohai
yohai

Reputation: 478

If the distribution is not important and all you're interested in is the mean, then there's a particularly simple function that does that:

function x=myrand
 x=6;
end

Upvotes: 1

yuk
yuk

Reputation: 19880

Here is an algorithm with a loop to reach a required mean xmean (with required precision xeps) by regenerating a random number from one half of a vector to another according to mean at current iteration. With my tests it reached the mean pretty quick.

n = 100;
xmean = 6;
xmin = 1;
xmax = 9;
xeps = 0.01;
x = randi([xmin xmax],n,1);
while abs(xmean - mean(x)) >= xeps
    if xmean > mean(x)
        x(find(x < xmean,1)) = randi([xmean xmax]);
    elseif xmean < mean(x)
        x(find(x > xmean,1)) = randi([xmin xmean]);
    end
end

x is the output you need.

Upvotes: 2

Ali
Ali

Reputation: 19712

You can use randi to get random integers

Upvotes: 2

High Performance Mark
High Performance Mark

Reputation: 78364

You may be able to define a function that satisfies your requirements based on Matlab's randi function. But be careful, it is easy to define functions of random number generators which do not produce random numbers.

Another approach might suit -- create a probability distribution to meet your requirements. In this case you need a vector of 9 floating-point numbers which sum to 1 and which, individually, express the probability of the i-th integer occurring. For example, a distribution might be described by the following vector:

[0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1]

These split the interval [0,1] into 9 parts. Then, take your favourite rng which generates floating-point numbers in the range [0,1) and generate a number, suppose it is 0.45. Read along the interval from 0 to 1 and you find that this is in the 5-th interval, so return the integer 5.

Obviously, I've been too lazy to give you a vector which gives 6 as the mean of the distribution, but that shouldn't be too hard for you to figure out.

Upvotes: 4

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272677

You could use floor to truncate your random numbers to integer values only:

r = 1 + floor(9 * rand(100,1));

Obtaining a specified mean is a little trickier; it depends what kind of distribution you're after.

Upvotes: 1

Related Questions