changing probability of getting a random number

2019-01-18 14:53发布

I would like to generate a random number between 0 and 3 and I have the following in my code:

int random = rand() % 4;

This works fine but I would like it to generate 1, 2, and 3 most of the time and 0 only occasionally.

What is the best way to go about this? What are the names of common algorithms to address this problem?

标签: c++ random
7条回答
何必那么认真
2楼-- · 2019-01-18 15:06

how many numbers have you tested this on? if it is actually true you can instead generate a range from say 0->3999 using a = rand()%4000 and use int = a/1000 this should remove the weight of the apparently under produced zero.

查看更多
叼着烟拽天下
3楼-- · 2019-01-18 15:06

Just code exactly what you want:

int myrand(void)
{
    const int percentZero = 10;
    if ((rand()%100) < percentZero) return 0;
    return 1 + (rand() % 3);
}

You can change the percentage of time zero is returned to whatever you want.

查看更多
Evening l夕情丶
4楼-- · 2019-01-18 15:06

You need to find a probability distribution that works for your case. Since you're only talking about the numbers 0-3 this is quite easy, you could either call rand() again if the first result is a 0, or you could use weights:

int random = rand() % 16;

if(random > 10)
{
    random = 3;
}
else if(random > 5)
{
    random = 2;
}
else if(random > 0)
{
random = 1;
}

This isn't a particularly elegant, but hopefully it shows you how you can create a custom distribution to fit your needs.

查看更多
beautiful°
5楼-- · 2019-01-18 15:08

You didn't give exact proportions, but suppose you want 1, 2, and 3 to each occur 32% of the time, and 0 to occur the other 4%. Then you could write:

int random = rand() % 25;
if(random > 0)
    random = random % 3 + 1;

(Obviously you'd need to adjust that for different proportions. And the above is just one approach; many similar approaches could work.)

查看更多
你好瞎i
6楼-- · 2019-01-18 15:13

Here's one way. Suppose you want 0, 1, 2, 3 to have a distribution of 5%, 20%, 30%, 45%.
You could do it like this:

double val = (double)rand() / RAND_MAX;

int random;
if (val < 0.05)       //  5%
    random = 0;
else if (val < 0.25)  //  5% + 20%
    random = 1;
else if (val < 0.55)  //  5% + 20% + 30%
    random = 2;
else
    random = 3;

Of course it doesn't have to be done with floating-point. I just did it this way since it's more intuitive.

查看更多
可以哭但决不认输i
7楼-- · 2019-01-18 15:20

You can use the discrete_distribution class from the random library.

#include <iostream>
#include <random>
#include <ctime>

int main()
{
    std::discrete_distribution<> dist({ 1.0, 4.0, 4.0, 4.0 });  
    std::mt19937 eng(std::time(0));
    for (int i=0; i<100; ++i)
        std::cout << dist(eng);
}

Demo: http://ideone.com/z8bq4

If you can't use C++11, these classes also exist in boost.

查看更多
登录 后发表回答