我的输出是20个随机1,而不是10和1之间,任何人都可以解释为什么会发生这种情况?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand((unsigned)time(0));
int random_integer;
int lowest=1, highest=10;
int range=(highest-lowest)+1;
for(int index=0; index<20; index++){
random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0));
cout << random_integer << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Rob*_*obᵩ 38
因为,在你的平台上,RAND_MAX == INT_MAX.
表达式range*rand()永远不会占用大于的值INT_MAX.如果数学表达式大于INT_MAX,则整数溢出将其减少为INT_MIN和之间的数字INT_MAX.除以RAND_MAX它将始终产生零.
试试这个表达式:
random_integer = lowest+int(range*(rand()/(RAND_MAX + 1.0)))
Run Code Online (Sandbox Code Playgroud)
bam*_*s53 16
<random>正确使用库比rand(假设你对C++足够熟悉,语法不会引起你)要容易得多.
#include <random>
#include <iostream>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
std::uniform_int_distribution<> dist(1, 10);
for(int i = 0; i < 20; ++i)
std::cout << dist(eng) << " ";
}
Run Code Online (Sandbox Code Playgroud)
ryo*_*ung 11
random_integer = (rand() % 10) + 1
Run Code Online (Sandbox Code Playgroud)
这应该给你一个介于1和10之间的伪随机数.
一个稍晚的答案,但如果一代的质量很重要,它应该提供一些额外的信息.(并非所有应用程序都需要这一点 - 轻微的偏差通常不是问题.)
首先,当然,原始代码中的问题是range * rand()优先于以下除法的事实
,并且使用整数运算来完成.取决于RAND_MAX,这很容易导致溢出,实现定义结果; 在我知道的所有实现中,如果它确实导致溢出(因为
RAND_MAX > INT_MAX / range,实际结果几乎肯定会小于RAND_MAX + 1.0,并且除法将导致值小于1.0.有几种方法可以避免这种情况:最简单,最可靠很简单rand() % range + lowest.
请注意,这假设rand()质量合理.许多早期的实现都没有,而且我已经看到至少有一个
rand() % 6 + 1模拟掷骰子交替奇数和偶数的地方.这里唯一正确的解决方案是更好地实现
rand(); 它导致人们尝试替代解决方案,例如
(range * (rand() / (RAND_MAX + 1.0))) + lowest.这掩盖了问题,但它不会将坏的发电机改成好的发电机.
第二个问题,如果生成的质量很重要,那就是当生成随机整数时,你就是离散化:例如,如果你正在模拟掷骰子,你有六个可能的值,你想要发生概率相等.随机生成器将以RAND_MAX + 1相同的概率生成不同的值.如果RAND_MAX + 1不是6的倍数,则没有可能的方法来分配值,而不是6个期望的值.想象一下简单的情况RAND_MAX + 1是10.使用%上面的
方法,值1-4的值是值5和6的两倍.如果使用更复杂的公式1 + int(6 *
(rand() / (RAND_MAX + 1.0)))(在这种情况下RAND_MAX + 1 == 10,结果是3和6它们只有其他值的一半.数学上,根本没有办法将10个不同的值分配到6个槽中,每个槽中的元素数量相等.
当然,RAND_MAX总是会比10大得多,而且引入的偏差也会大大减少; 如果范围明显小于RAND_MAX,则可以接受.但是,如果不是这样,通常的程序是这样的:
int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range;
// 1LL will prevent overflow on most machines.
int result = rand();
while ( result >= limit ) {
result = rand();
}
return result % range + lowest;
Run Code Online (Sandbox Code Playgroud)
(有几种方法可以确定要丢弃的值.这恰好是我使用的那个,但我记得Andy Koenig使用了一些完全不同的东西 - 但最终会导致相同的值被抛出.)
请注意,大多数情况下,您不会进入循环; 最坏的情况是,当range是(RAND_MAX + 1) / 2 + 1,在这种情况下,你仍然只是通过循环平均一次下.
请注意,这些注释仅适用于需要固定数量的离散结果的情况.对于范围内产生一个随机浮点数的(其他)常见的情况[0,1),rand() / (RAND_MAX +
1.0)是因为你要得到的一样好.