2010-03-10 149 views
3

我正在学习编程课程,我们正在使用C++。 我们有一个任务,在某些时候,我们需要编写一个函数,以[上限,下限]间隔返回一个随机数。我用下面的:随机数生成问题

lower + (int) (upper * (rand()/(RAND_MAX + 1.0))); 

我没有忘记用srand((unsigned int) time(0))改变srand

但是,我每次都得到相同的价值!我请求教授寻求帮助,经过一番调查,他发现rand()生成的第一个数字不是随机的......高阶位保持不变,并且由于此实现使用它们,所以最终结果不是完全是我所期望的。

是否有一个更优雅,但简单的解决方案,而不是放弃第一个值或使用余数来实现我想要的?

非常感谢您的关注!

〜Francisco

编辑:谢谢大家的意见。我不知道rand()是这样一个很烂的RNG:P

+0

是不是'rand()'过时了?我认为现在每个人都应该使用'random()'。 – 2010-03-10 19:39:20

+0

'lower + rand()%(upper - lower + 1)'有什么问题?你为什么不想用余数? – IVlad 2010-03-10 19:39:53

+2

只是在说我也注意到了这一点。如果你实际上每次发现它不完全相同时打印出第一个rand(),但这些数字都相当接近。例如,现在当我连续多次开始一个程序时,我都会将数字全部在23000范围内,例如作为第一个数字。之后,数字更随机。我一直只是抛弃了像你提到的第一个rand()数字。 – 2010-03-10 19:42:29

回答

2

鉴于rand()不是一个非常强的随机数生成器,标准方法添加的少量偏差可能不是问题:(更高 - 更低)当然需要小于MAX_RAND。

lower + rand() % (higher-lower+1); 

由一个错误的固定关断。

+0

'lower + rand()%(higher-lower + 1);' – IVlad 2010-03-10 19:42:11

+0

这将是'lower + rand()%(higher-lower + 1);' 出于学术的好奇,我想得到一个这个问题的解决方案不同,但感谢您的意见。 :) – 2010-03-10 19:45:05

1

rand()不是一个好的随机数发生器。除了你观察到的问题之外,它的周期长度可能很短。

考虑使用gsl random number generators之一。

+0

感谢您的链接! – 2010-03-10 19:48:54

1

根据您正在使用的操作系统,除rand()之外,还可能有random()。这产生比rand()好得多的伪随机数。请检查<stdlib.h>和/或man 3 random

1

你的代码是好的,但你应该取代

lower + (int) upper * (rand()/(RAND_MAX + 1.0)); 

lower + (int) (upper - lower + 1)*(rand()/(RAND_MAX + 1.0)); 

下面的代码工作很好地在我的机器上:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#define lower 10 
#define upper 20 

int main(void) 
{ 
    int i; 
    int number; 

    srand(time(0)); 
    for(i=0; i<10; i++) 
    { 
     number = lower + (int) (upper - lower + 1)*(rand()/(RAND_MAX + 1.0)); 
     printf ("%d\n", number); 
    } 

    return 0; 
}  

当然,因为time(0)给目前时间在几秒钟内 ,同一秒内两次执行的结果相同。

+2

“rand()以秒为单位给出当前时间” - 这是一个奇怪的实现。 :P – Bill 2010-03-10 20:53:21

+1

@ Bill:哦,呃,好吧......它仍然是一个无证的功能。绝密。不要告诉任何人 – 2010-03-10 21:13:19

1

C++ 0x随机数字库(也可在TR1和Boost中使用)最终解决了一些令人讨厌的兰特问题。它允许获得真正的随机性(random_device),你可以使用它来进行适当的播种,然后你可以使用一个快速且良好的伪随机生成器(mt19937),并且你可以使用一个合适的分布(例如uniform_int,每个值的概率)。

它也不像Rand()那样使用全局隐藏状态,所以在多线程程序中不会有任何问题。

由于所有的模块化,使用起来比简单地调用rand要困难一些,但是仍然有益处远远超过了陡峭的学习曲线。