我正在尝试用骰子制作游戏,我需要在其中有随机数字(模拟模具的两侧.我知道如何在1到6之间进行).运用
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
srand((unsigned)time(0));
int i;
i = (rand()%6)+1;
cout << i << "\n";
}
Run Code Online (Sandbox Code Playgroud)
效果不好,因为当我运行程序几次时,这是我得到的输出:
6
1
1
1
1
1
2
2
2
2
5
2
Run Code Online (Sandbox Code Playgroud)
所以我想要一个每次都会产生不同随机数的命令,而不是连续5次产生不同的随机数.有没有命令可以做到这一点?
Cor*_*lks 165
使用模可以将偏差引入随机数,这取决于随机数发生器.有关详细信息,请参阅此问题.当然,完全有可能以随机顺序重复数字.
尝试一些C++ 11功能以便更好地分发:
#include <random>
#include <iostream>
int main()
{
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]
std::cout << dist6(rng) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
有关C++ 11随机数的更多信息,请参阅此问题/答案.以上不是唯一的方法,但这是一种方式.
Ser*_*ich 57
测试应用程序的最基本问题是您调用srand
一次,然后调用rand
一次并退出.
整个srand
功能点是用随机种子初始化伪随机数序列.这意味着如果您将相同的值传递给srand
两个不同的应用程序(具有相同srand
/ rand
实现),那么您将获得完全相同的rand()
值序列.但是你的伪随机序列只包含一个元素 - 你的输出由不同的伪随机序列的第一个元素组成,这些元素以1秒精度的时间播种.那你期望看到什么?当您碰巧在同一秒运行应用程序时,您的结果当然是相同的(正如Martin York在答案评论中已提到的那样).
实际上你应该拨打srand(seed)
一次,然后rand()
多次打电话并分析这个序列 - 它应该是随机的.
小智 12
每当您random number generation
在 C++ 编程语言中进行基本的网络搜索时,这个问题通常是第一个弹出的问题!我想把我的帽子扔进戒指,希望能更好地阐明C++中伪随机数生成的概念,以便将来不可避免地在网络上搜索相同问题的编码人员!
伪随机数生成涉及利用确定性算法的过程,该算法生成性质近似于随机数的数字序列。我说近似相似,因为真正的随机性在数学和计算机科学中是一个相当难以捉摸的谜。因此,为什么使用术语伪随机来更迂腐正确!
在您实际使用 PRNG 之前,即,pseudo-random number generator
您必须为算法提供一个初始值,通常也称为种子。但是,在使用算法本身之前,必须只设置一次 种子!
/// Proper way!
seed( 1234 ) /// Seed set only once...
for( x in range( 0, 10) ):
PRNG( seed ) /// Will work as expected
/// Wrong way!
for( x in rang( 0, 10 ) ):
seed( 1234 ) /// Seed reset for ten iterations!
PRNG( seed ) /// Output will be the same...
Run Code Online (Sandbox Code Playgroud)
因此,如果您想要一个好的数字序列,那么您必须为 PRNG 提供充足的种子!
C++ 具有的向后兼容的 C 标准库,使用了在头文件中找到的所谓的线性同余生成器cstdlib
!此 PRNG 通过使用模算术的不连续分段函数(即喜欢使用modulo operator '%'
. 以下是此 PRNG 的常见用法,关于@Predictability 提出的原始问题:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main( void )
{
int low_dist = 1;
int high_dist = 6;
std::srand( ( unsigned int )std::time( nullptr ) );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << low_dist + std::rand() % ( high_dist - low_dist ) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C 的 PRNG 的常见用法包含大量问题,例如:
std::rand()
对于在给定范围之间正确生成伪随机数,例如,以@Predictability 想要的方式生成 [1, 6] 之间的数字,的整体界面不是很直观。std::rand()
消除了伪随机数均匀分布的可能性。std::rand()
播种的常用方法std::srand( ( unsigned int )std::time( nullptr ) )
是不正确的,因为time_t
被认为是受限制的类型。因此,不能保证从time_t
到的转换unsigned int
!有关使用 C 的 PRNG 的整体问题以及如何规避这些问题的更多详细信息,请参阅使用 rand() (C/C++):对 C 标准库的 rand() 函数的建议!
自从 ISO/IEC 14882:2011 标准(即 C++11)发布random
以来,该库已经成为 C++ 编程语言的一部分已有一段时间了。该库配备了多个PRNG,以及不同的分布类型,例如:均匀分布、正态分布、二项分布等。以下源代码示例演示了该random
库的一个非常基本的用法,关于@Predictability 的原始问题:
#include <iostream>
#include <cctype>
#include <random>
using u32 = uint_least32_t;
using engine = std::mt19937;
int main( void )
{
std::random_device os_seed;
const u32 seed = os_seed();
engine generator( seed );
std::uniform_int_distribution< u32 > distribute( 1, 6 );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << distribute( generator ) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
32位梅森倍捻机发动机,具有均匀分布的整数值被利用在上述的例子。(源代码中引擎的名字听起来很奇怪,因为它的名字来自它的时期2^19937-1 )。该示例还用于std::random_device
为引擎设置种子,该引擎从操作系统获取其值(如果您使用的是 Linux 系统,std::random_device
则从 返回一个值/dev/urandom
)。
请注意,您不必使用std::random_device
种子任何引擎。您可以使用常量甚至chrono
库!您也不必使用 32 位版本的std::mt19937
引擎,还有其他选择!有关random
库功能的更多信息,请参阅cplusplus.com
总而言之,C++ 程序员不应该再使用std::rand()
了,不是因为它不好,而是因为当前的标准提供了更好的替代方案,更直接和可靠。希望你们中的许多人发现这很有帮助,尤其是那些最近在网上搜索的人generating random numbers in c++
!
mad*_*adx 10
如果您使用的是升压库,则可以通过以下方式获取随机生成器:
#include <iostream>
#include <string>
// Used in randomization
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
using namespace std;
using namespace boost;
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
int main (int argc, char* argv[]) {
unsigned int dice_rolls = 12;
random::mt19937 rng(current_time_nanoseconds());
random::uniform_int_distribution<> six(1,6);
for(unsigned int i=0; i<dice_rolls; i++){
cout << six(rng) << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
其中函数current_time_nanoseconds()
给出当前时间(以纳秒为单位),用作种子.
这是一个更通用的类,用于获取范围内的随机整数和日期:
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
bool method() { return true; };
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
// Is not considering the millisecons
time_duration rand_time_duration(){
boost::posix_time::time_duration floor(0, 0, 0, 0);
boost::posix_time::time_duration ceil(23, 59, 59, 0);
unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
return seconds(rand_seconds);
}
date rand_date_from_epoch_to_now(){
date now = second_clock::local_time().date();
return rand_date_from_epoch_to_ceil(now);
}
date rand_date_from_epoch_to_ceil(date ceil_date){
date epoch = ptime(date(1970,1,1)).date();
return rand_date_in_interval(epoch, ceil_date);
}
date rand_date_in_interval(date floor_date, date ceil_date){
return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
}
ptime rand_ptime_from_epoch_to_now(){
ptime now = second_clock::local_time();
return rand_ptime_from_epoch_to_ceil(now);
}
ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
ptime epoch = ptime(date(1970,1,1));
return rand_ptime_in_interval(epoch, ceil_date);
}
ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
time_duration const diff = ceil_date - floor_date;
long long gap_seconds = diff.total_seconds();
long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
return floor_date + seconds(step_seconds);
}
};
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
srand(time(NULL));
int random_number = std::rand(); // rand() return a number between ?0? and RAND_MAX
std::cout << random_number;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
http://en.cppreference.com/w/cpp/numeric/random/rand
如果您需要在项目的不同部分使用随机数,您可以创建一个单独的类Randomer
来封装其中的所有random
内容。
类似的东西:
class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;
public:
/* ... some convenient ctors ... */
Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}
// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}
size_t operator()() {
return dist_(gen_);
}
};
Run Code Online (Sandbox Code Playgroud)
这样的类稍后会很方便:
int main() {
Randomer randomer{0, 10};
std::cout << randomer() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
您可以查看此链接作为我如何使用此类Randomer
生成随机字符串的示例。Randomer
如果您愿意,您也可以使用。
归档时间: |
|
查看次数: |
367210 次 |
最近记录: |