我的输出是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;
}
}
输出: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
答案 0 :(得分: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)))
答案 1 :(得分: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) << " ";
}
答案 2 :(得分:11)
random_integer = (rand() % 10) + 1
那应该给你一个介于1和1之间的伪随机数。 10。
答案 3 :(得分:9)
一个稍晚的答案,但它应该提供一些额外的 信息如果代的质量很重要。 (不是全部 应用程序需要这一点 - 轻微的偏差通常不是问题。)
首先,当然,原始代码中的问题是这样的事实
range * rand()
优先于以下分区,并且已完成
使用整数运算。根据{{1}},这很容易
导致溢出,实现定义结果;所有
我知道的实现,如果它确实导致溢出(因为
RAND_MAX
,实际结果几乎可以肯定
小于RAND_MAX > INT_MAX / range
,除法将导致a
值小于RAND_MAX + 1.0
。有几种方法可以避免这种情况:
最简单,最可靠的只是1.0
。
请注意,这假设rand() % range + lowest
质量合理。许多
早期的实现不是,我已经看到至少一个在哪里
rand()
模拟骰子投掷交替奇数和偶数。该
这里唯一正确的解决方案是获得更好的实现
rand() % 6 + 1
;它导致人们尝试替代解决方案,例如
rand()
。这掩盖了
问题,但它不会将坏的发电机变成一个好的发电机。
第二个问题,,如果代的质量很重要,是
当生成随机整数时,你就是离散的:如果你是
例如,模拟掷骰子,你有六种可能
您希望以相同的概率发生的值。随机
生成器将生成(range * (rand() / (RAND_MAX + 1.0))) + lowest
个不同的值,具有相同的值
可能性。如果RAND_MAX + 1
不是6的倍数,那就没有
分配价值的可能方式等于所需的6
值。想象一下RAND_MAX + 1
为10的简单情况。使用
上面的RAND_MAX + 1
方法,值1-4的可能性是其中的两倍
值5和6.如果使用更复杂的公式%
(在1 + int(6 *
(rand() / (RAND_MAX + 1.0)))
的情况下,
事实证明,3和6只是其他值的一半。
在数学上,根本没有办法分配10种不同的
将值分配到6个槽中,每个槽中具有相同数量的元素。
当然,RAND_MAX + 1 == 10
总是比10大得多,而且
引入的偏差将会大大减少;如果范围是
显着低于RAND_MAX
,这是可以接受的。如果它是
但是,通常的程序不是这样的:
RAND_MAX
(有几种方法可以确定丢弃的值。这个 碰巧是我使用的那个,但我记得Andy Koenig使用的东西 完全不同 - 但导致相同的价值观 最后抛出。)
请注意,大多数情况下,您不会进入循环;最糟糕的情况是
当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;
为range
时,在这种情况下,您仍然会
通过循环平均不到一次。
请注意,这些注释仅适用于您需要固定数量的注释
离散的结果。对于生成随机的(其他)常见情况
(RAND_MAX + 1) / 2 + 1
范围内的浮点数,[0,1)
与您将得到的一样好。
答案 4 :(得分:1)
我建议您将rand()/(RAND_MAX + 1.0)
替换为range*double(rand())/(RAND_MAX + 1.0))
。因为我的解决方案似乎令人头疼......
可能的参数组合:
range*rand()
是一个整数并溢出。double(range*rand())
在将其转换为double之前溢出。range*double(rand())
没有溢出并产生预期结果。我的原帖有两个大括号,但它们没有改变任何东西(结果是一样的)。
答案 5 :(得分:1)
Visual Studio 2008对该程序没有任何问题,并且愉快地生成大量随机数。
我要小心的是/(RAND_MAX +1.0),因为这可能会导致整数问题,并最终导致大量的零点。
在分割之前强制转换为double,然后再将其转换为int
答案 6 :(得分:1)
(rand() % highest) + lowest + 1
答案 7 :(得分:0)
您正在生成一个随机数(即(range*rand()/(RAND_MAX + 1.0))
),其值介于-1和1之间(]-1,1[
),然后将其转换为整数。此数字的整数值始终为0,因此您最终得到lower + 0
编辑:添加公式以使我的回答更清晰
答案 8 :(得分:0)
可能“10 * rand()”小于“RAND_MAX + 1.0”,因此您的计算值为0.
答案 9 :(得分:0)
这是最简单的逻辑之一,从博客中获取。在这个逻辑中,您可以使用for循环中给定的模数(%)运算符限制随机数,它只是来自该博客的copoy和粘贴,但无论如何都要检查它:
// random numbers generation in C++ using builtin functions
#include <iostream>
using namespace std;
#include <iomanip>
using std::setw;
#include <cstdlib> // contains function prototype for rand
int main()
{
// loop 20 times
for ( int counter = 1; counter <= 20; counter++ ) {
// pick random number from 1 to 6 and output it
cout << setw( 10 ) << ( 1 + rand() % 6 );
// if counter divisible by 5, begin new line of output
if ( counter % 5 == 0 )
cout << endl;
}
return 0; // indicates successful termination
} // end main
- 详情请见:http://www.programmingtunes.com/generation-of-random-numbers-c/#sthash.BTZoT5ot.dpuf
答案 10 :(得分:0)
如果使用条件检查最后一个数字是否与当前数字相同?如果满足条件,则生成另一个随机数。这个解决方案有效,但需要更多时间。