我想生成一个随机数,每个数字都在 0-9 范围内并且不重复。假设有限长度为 4。
- 1234 符合条件,每个复合数字都是唯一的。
- 1123没有,1重复
请问这怎么做?
要生成数字:
std::vector<int> vec = {0,1,2,3,4,5,6,7,8,9}; // or initialize from array if not c++11
std::random_shuffle(vec.begin(), vec.end());
vec.resize(4);
并将数字连接成一个数字:
int number = 0;
for (auto i = vec.begin(); i != vec.end(); ++i) {
number = 10 * number + (*i);
}
我相信您正在谈论生成排列。
尝试这样的事情:
int used[10] = {0};
int n = 0;
int number = 0;
while( n < 10 ) {
int d = rand() % 10;
if( used[d] ) continue;
used[d] = 1;
number = number * 10 + d;
n++;
}
不是最有效的......它只是跟踪已使用的数字,并在遇到使用的数字时重新滚动。
以上确实有副作用,如果零是选择的第一个数字,则在技术上不使用零。您可以明确阻止这种情况,或者简单地接受某些数字的长度为 9 位。
如果您宁愿避免不必要地使用 std::vector 和它带来的内存分配,可能会在 random_shuffle 中使用过多的随机化调用,如果您玩一些数学,那么有一种更简单的方法。
如果您可以计算存在多少有效(即可接受的)序列C,并且您可以设计一个从该计数器映射到每个有效序列实例的双射函数,那么事情就变得微不足道了。在 [0, C )范围内生成一个随机整数,将其插入返回有效输出的函数中。
如果我正确理解您的示例,您希望生成一个随机的 4 位序列 ABCD(表示 [0,9999] 范围内的整数),其中数字A、B、C和D彼此不同。
有 5040 个这样的有效序列:10 * 9 * 8 * 7。
给定 [0, 5039] 范围内的任何整数,以下函数将返回一个有效序列(即每个数字都是唯一的),表示为整数:
int counter2sequence(int u) {
int m = u/504;
u %= 504;
int h = u/56;
u %= 56;
int t = u/7;
u %= 7;
const int ih = h;
const int it = t;
if (ih >= m) ++h;
if (it >= ih) ++t;
if (t >= m) ++t;
if (u >= it) ++u;
if (u >= ih) ++u;
if (u >= m) ++u;
return ((m*10 + h)*10 + t)*10 + u;
}
例如
counter2sequence(0) => 0123
counter2sequence(5039) => 9876