SRAND 不帮助我创建随机数
srand doesn't help me creating random numbers
我正在试着洗牌。我随机创建两个数字,并将它们的值相互分配100次。但它并不是随机产生的。最奇怪的是,我在"counter++;"行放了一个断点,观察程序是否真的每次都选择不同的卡。当我调试时,如果我点击继续按钮太快,它每次都会创建相同的index1和index2(但index1不等于index2)。我想可能是时间原因。(当我点击继续按钮的速度太快,或者根本没有设置断点时,由于时间相同,它会创建相同的数字。)但如果是这样的话,为什么程序会为index1和index2创建不同的值?它们的行之间没有断点。所以时间一定很短。不过,它会创建不同的索引。我很困惑。如何摆脱?
编辑:解决方案主要是使用srand一次。
void mix(string *a){
srand(time(NULL));
if (finisher == 100){
return;
}
string b;
int pos1;
pos1 = rand() % 52;
b = a[pos1];
int pos2;
pos2 = rand() % 52;
cout << a[pos1] << " " << a[pos2] << endl; //These lines are only for testing
a[pos1] = a[pos2];
a[pos2] = b;
cout << a[pos1] << " " << a[pos2] << endl; //These lines are only for testing
counter++;
srand(time(NULL));
mix(a);
}
如果使用srand
设置特定种子,rand
将生成特定的伪随机整数序列
来自man rand
:
srand()
函数将其参数设置为新序列的种子由CCD_ 5返回的伪随机整数这些序列可通过调用具有相同种子值的srand()
来重复
time(NULL)
每秒只会改变一次,所以你会经历这样的行为
此外,正如@LightnessRacesinOrbit在一些评论中提到的那样,您应该只调用srand
一次。
从C++11开始,就有了<random>
标头改为使用它
根据http://en.cppreference.com/w/cpp/numeric/random/srand
注意:
一般来说,伪随机数生成器只应在任何对rand()的调用之前和程序启动之前播种一次。它不应该重复播种,也不应该在每次希望生成新一批伪随机数时重新播种。
标准做法是使用对时间(0)的调用结果作为种子。但是,time()返回一个time_t值,并且不能保证time_t是一个整型。然而,在实践中,每个主要实现都将time_t定义为一个积分类型,这也是POSIX所要求的。
顺便说一句,你为什么不使用C++11随机数生成器,它会产生均匀分布在闭区间[a,b]上的随机整数值i,,也就是说,根据离散概率函数分布。看见http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
提供的示例代码是cppreference页面。
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 51);
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << 'n';
}
您可能在调用srand时遇到问题。您的程序在一秒内多次运行shuffle_cards函数。这意味着您在srand(time(NULL));
中提供给srand的时间戳在多个调用中是相同的。
具有相同种子的两个不同初始化将在对rand的后续调用中生成相同的连续结果。
因此,两次rand()调用都将生成与shuffle_cards函数的第一次调用相同的index1和index2数字。
解决方案是不调用srand或只调用一次,例如在程序启动时,或者不经常调用它。
正如其他人所说,问题的一部分是对srand
的所有调用。只叫一次。
这不是你所要求的,但代码不是一个很好的洗牌方法。首先,shuffle
应该用一个循环来编写,而不是调用它自己:
void shuffle(string* a) {
for (int i = 0; i < 100; ++i) {
int index1 = std::rand() % 52;
int index2 = std::rand() % 52;
string temp = a[index1];
a[index1] = a[index2];
a[index2] = temp;
}
}
请注意,这段代码使用初始化,而不是定义一个未初始化的变量,然后为其赋值。此外,我还重新安排了顺序,以使其更清楚地了解发生了什么。
但这仍然不是洗牌的好方法;它通常会使甲板的大部分保持不变。这是一个众所周知的问题。阅读费雪-耶茨洗牌:
void shuffle(string* a) {
for (int i = 0; i < 51; ++i) {
int idx = std::rand() % (52 - i) + i;
string temp = a[idx];
a[idx] = a[i];
a[i] = temp;
}
}
这可以通过使用标准库的swap
函数来改进:
void shuffle(string* a) {
for (int i = 0; i < 51; ++i) {
int idx = std::rand() % (52 - i) + i;
std::swap(a[i], a[idx];
}
}
而且,除非你把这作为一种学习练习,否则你可以去掉所有的代码:
void shuffle(string* a) {
std::random_shuffle(a, a + 52);
}
注意,我已经假设这里的string
是char
或类似于char的东西的一些时髦的typedef,而不是std::string
,这些代码都不能正常工作。
- 尝试在 c++ 中创建随机数生成器并收到错误
- 创建一个带有随机数的向量
- 创建整数的 2D 数组,该数组将使用两个函数用随机数填充矩阵.我做错了什么?
- 如何在C++中创建数字列表,以便它可以选择一个随机数?
- 在 c++ 中创建具有指数分布的随机数(可视化标准)
- 用于创建高斯随机数的 c++ 函数
- 使用MersenneTwister从泊松区创建随机数
- 如何在C 中创建正常分布式随机数生成器的数组
- 在C++中创建随机数矩阵,无需循环
- 使用具有唯一随机数的结构数组创建多个对象
- visual如何在C++中创建一个随机数数组
- 创建双格式的随机数,eclipse停止工作
- 另一种创建随机数的方法
- 创建一个函数以返回指定范围内的随机数
- SRAND 不帮助我创建随机数
- 随机数生成器不断创建2
- 我正在尝试创建一个程序,该程序根据用户输入的最大值将随机数相乘
- rand() 不创建随机数
- 如何创建两个独立的对象,显示随机数10次
- 我能让我的while循环在每次循环时创建一个新的随机数吗