简体   繁体   中英

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

I need to generate random numbers with following properties.

  • Min must be 1
  • Max must be 9
  • Average (mean) is 6.00 (or something else)
  • Random number must be Integer (positive) only

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.

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.

您可以使用randi获取随机整数

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.

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.

Before you can design your random number generator you need to specify the distribution it should draw from. You've only partially done that: ie, 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: ie,

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: ie,

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM