我正在制作一个随机数生成器。它询问用户想要多少位数。例如,它输入2它将产生10到99之间的随机数。我已经制作了发生器,但我的问题是数字不是唯一的。
这是我的代码。我不确定为什么它没有产生唯一的数字。我认为srand(time(null))会这样做。
void TargetGen::randomNumberGen()
{
srand (time(NULL));
if (intLength == 1)
{
for (int i = 0; i< intQuantity; i++)
{
int min = 1;
int max = 9;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
else if (intLength == 2)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 10;
int max = 90;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
if (intLength == 3)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 100;
int max = 900;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
else if (intLength == 4)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 1000;
int max = 9000;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
if (intLength == 5)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 10000;
int max = 90000;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
else if (intLength == 6)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 100000;
int max = 900000;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
if (intLength == 7)
{
for (int i = 0; i<intQuantity; i++)
{
int min = 1000000;
int max = 9000000;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
else if (intLength == 8)
{
for (int i = 0; i <intQuantity; i++)
{
int min = 10000000;
int max = 89999999;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
if (intLength == 9)
{
for (int i = 0; i < intQuantity; i++)
{
int min = 100000000;
int max = 900000000;
int number1 = rand();
if (intQuantity > max)
{
intQuantity = max;
}
cout << number1 % max + min << "\t";
}
}
}
好吧所以我想我找到了一种没有阵列的方法,但是在我切换到fisher yates方法之前它还没有工作。有人能告诉我为什么这不起作用吗?它应该基本上把随机数放入变量numGen。然后在变量b =到numgen。只是为了保持numGen曾经是这样,当循环通过并生成另一个随机数时,它会将它与旧数字进行比较,如果它不等于它,那么它将输出它。如果它等于旧的数字而不是输出它,它将减去i,使其在没有完全跳过数字的情况下运行循环。但是,当我这样做时,无限循环。而且我不确定为什么。
if(intLength == 1) {
for (int i = 0; i< intQuantity; ++i)
{
int min = 1;
int max = 9;
int number1 = rand();
int numGen = number1 % max + min;
if (intQuantity > max)
{
intQuantity = max;
}
for (int k = 0; k < 1; k++)
{
cout << numGen << "\t";
int b = numGen;
}
int b = numGen;
if (b != numGen )
{
cout << numGen << "\t";
}
else
{
i--;
}
}
}
答案 0 :(得分:2)
每个人都对随机数有一个有趣的期望 - 显然,你希望随机数是唯一的!如果您使用任何好随机数生成器,您的随机数将 永远 保证是唯一的。
为了使这一点最明显,如果你想生成[1,2]范围内的随机数,并且你要生成两个数字,你会(通常期望)以相同的概率得到以下四种可能之一:
1,2 2,1 1,1 2,2,
要求一个好的随机数生成器生成前两个,而不是最后两个生成没有意义。
现在,如果你要求在同一范围内生成三个数字,请花一点时间思考会发生什么...... 1,2,然后是什么?
因此,唯一性不是,也不会是随机数生成器的属性。
但是,您的具体问题可能需要独特性。在这种情况下,您需要做一些额外的工作以确保唯一性。
一种方法是保留一个已经选择了数字的标签。你可以将它们保存在一个集合中,如果你得到了之前的那个,就重新挑选它们。但是,只有当您选择与您的范围相比较少的一组数字时,这才有效;如果你选择了大部分范围,那么这个过程的结束就会失效。
如果你要选择的数字计数对应于大部分范围,那么使用范围的数组,并使用一个好的改组算法来改变数字周围是一个更好的解决方案。 (Fisher-Yates shuffle应该可以解决问题。)
答案 1 :(得分:2)
提示0: 使用数论中的 Quadratic residue ;整数 q 被称为二次余数模 p ,如果它与完全平方模 p 一致;即,如果存在整数 x ,则:
x 2 ≡q(mod p)
提示1: 定理:假设p是素数,x的二次余数是唯一的,只要2x <1。页。例如:
0 2 ≡0(mod 13)
1 2 ≡1(mod 13)
2 2 ≡4(mod 13)
3 2 ≡9(mod 13)
4 2 ≡3(mod 13)
5 2 ≡12(mod 13)
6 2 ≡10(mod 13)
提示2: 定理:假设p是素数,使得p≡3(mod 4),不仅x 2 %p(即二次余数)对于2x <1是唯一的。 p,但p-x 2 %p对于2x> p也是唯一的。例如:
0 2 %11 = 0
1 2 %11 = 1
2 2 %11 = 4
3 2 %11 = 9
4 2 %11 = 5
5 2 %11 = 3
11 - 6 2 %11 = 8
11 - 7 2 %11 = 6
11 - 8 2 %11 = 2
11 - 9 2 %11 = 7
11 - 10 2 %11 = 10
因此,这种方法在小于p的整数上为我们提供了完美的1对1排列,其中p可以是任何素数,使得p≡3(mod 4)。
提示3:
unsigned int UniqueRandomMapping(unsigned int x)
{
const unsigned int p = 11; //any prime number satisfying p ≡ 3 (mod 4)
unsigned int r = ((unsigned long long) x * x) % p;
if (x <= p / 2) return r;
else return p - r;
}
我并不担心输入数字不好(例如超出范围)。
<强>说明强>
答案 2 :(得分:1)
我假设您可以想出一个方法来确定您想要使用多少个数字。它非常简单,因为2的用户输入为10-99,3为100-999等。
如果您想要自己实现独特的,随机生成的数字,请查看这些链接。
http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
这是一个非常类似的实现:https://stackoverflow.com/a/196065/2142219
本质上,您正在创建一个X整数数组,所有这些都设置为其索引的值。您可以随机选择介于0和MAX之间的索引,获取此索引处的值并将其与最大值进行交换。然后将MAX递减1,您可以通过随机选择0和MAX之间的索引重复它。
这为你提供了一个0-999整数的随机数组,没有重复。
答案 3 :(得分:0)
以下是在范围内生成唯一随机数的两种可能方法。
std::set
跟踪您已经生成的数字,只要它们已经在集合中,就会丢弃并重新生成数字。由于生日悖论,如果你想生成大量的随机数,这种方法不推荐。答案 4 :(得分:0)
标准随机生成器永远不会生成唯一的数字,在这种情况下,它们不会是独立的。
要生成唯一的数字,您必须:
或
答案 5 :(得分:0)
首先,srand()
/ rand()
通常的周期为2 ^ 32,这意味着在调用srand()
之后,rand()
会在内部在对rand()
的前2 ^ 32次调用期间迭代不同的整数。尽管如此,rand()
可能会返回少于32位的结果:例如int
和0
之间的RAND_MAX
,其中RAND_MAX
为2 ^ 31-1或2 ^ 15-1,因此您可能会看到重复的结果作为rand()
的来电者。你可能已经读过这个时期,或者有人意识到这一点,并且不知怎的,它被误认为是唯一性......
其次,如果对rand()
的任何调用产生的数字远远大于您想要的数字,那么您就是这样做了......
number1 % max
&#34; number1 % max
&#34;的结果在0 <= N <= max
范围内,但随机数本身可能是max
的任意倍数。换句话说,两个不同的随机数相差max
的倍数,仍然会在程序中为number1 % max
生成相同的结果。
要获得某个范围内的不同随机数,您可以使用所有数字预填充std::vector
,然后std::shuffle
。