rand()和srand()
rand和srand,是C++中常用的随机数生成函数伪随机数生成函数。
其中 rand()函数不需要输入参数,它会返回0到RAND_MAX之间的任意的整数。如果我们想他返回[0,n-1]内的整数,我们可以写:
int x = rand()%n;
返回[0,1]
double x = rand()/RAND_MAX;;
但是,每当我们重新运行一次,得到的X的值总是保持一致,他们一开始随机的起点总是一致的,这是我们不想看到的,于是就有了srand()来引入不同随机种子的函数。
我们通常用time(0)来作为随机种子。即:
srand(time(0));
int x = rand();
time(0)会返回从1970 UTC Jan 1 00:00到现在时间的秒数,类型为unsigned int。所以每次运行会传入不同的种子,使得随机数不同,但这样还是一个伪随机数。
bug
当srand(time(0)),这个函数在一秒内反复执行的时候,它将不会更新随机数种子导致,rand()会一直生成一样的随机数,导致无法产生随机数,注意。
例题举例
参考例题:LeetCode528. 按权重随机选择
以下两种代码:代码1能过,后面的不行。
class Solution {
public:
long long sum = 0,n;
long long pre[100005] = {0};
vector<int> cw;
Solution(vector<int>& w) {
sum = pre[0] = w[0];
cw.push_back(w[0]);
for(int i=1;i< w.size();i++){
pre[i] += pre[i-1] + w[i];
cw.push_back(w[i]);
sum += w[i];
}
n = w.size()-1;
srand((int)time(0));
}
int pickIndex() {
int x = rand()%sum +1;
for(int i=0;i<cw.size();i++){
long long left = pre[i] - cw[i] +1;
long long right = pre[i];
if (x>= left && x<= right){
return i;
}
}
return 12123;
//return lower_bound(pre[0],pre[n],x) - pre[0] - 1;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/
代码2,无法通过,因为此处的srand会在一秒内被反复调用,导致随机数种子失效。
class Solution {
public:
long long sum = 0,n;
long long pre[100005] = {0};
vector<int> cw;
Solution(vector<int>& w) {
sum = pre[0] = w[0];
cw.push_back(w[0]);
for(int i=1;i< w.size();i++){
pre[i] += pre[i-1] + w[i];
cw.push_back(w[i]);
sum += w[i];
}
n = w.size()-1;
}
int pickIndex() {
srand((int)time(0));
int x = rand()%sum +1;
for(int i=0;i<cw.size();i++){
long long left = pre[i] - cw[i] +1;
long long right = pre[i];
if (x>= left && x<= right){
return i;
}
}
return 12123;
//return lower_bound(pre[0],pre[n],x) - pre[0] - 1;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/