可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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.
回答3:
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.)
回答4:
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.
回答5:
I would just map more values to 1,2,3 from a larger set. For example: 9 and map 1,2,3 => 1, 3,4,5=>2, 6,7,8=>3 and 0 for zero. There are other ways, but I am working within your question
回答6:
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.
回答7:
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.