216

我正在尝试用骰子制作游戏,并且我需要在其中包含随机数(以模拟骰子的侧面。我知道如何使其介于 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"; 
}

不能很好地工作,因为当我运行程序几次时,我得到的输出如下:

6
1
1
1
1
1
2
2
2
2
5
2

所以我想要一个每次都会生成不同随机数的命令,而不是连续 5 次相同的随机数。有没有命令可以做到这一点?

4

12 回答 12

271

根据随机数生成器的不同,使用模数可能会在随机数中引入偏差。有关更多信息,请参阅此问题。当然,完全有可能获得随机序列中的重复数字。

尝试一些 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;
}

有关 C++11 随机数的更多信息,请参阅此问题/答案。以上不是唯一的方法,而是一种方法。

于 2012-11-18T23:33:50.383 回答
130

您的测试应用程序最根本的问题是您调用srand一次,然后调用rand一次并退出。

函数的重点是用随机种子srand初始化伪随机数序列。

这意味着如果您将相同的值传递给srand两个不同的应用程序(具有相同的srand/rand实现),那么您将在两个应用程序中获得完全相同的rand()序列。

但是,在您的示例应用程序中,伪随机序列仅包含一个元素 - 从种子生成的伪随机序列的第一个元素等于当前1 sec精度时间。你期望在输出上看到什么?

显然,当您碰巧在同一秒运行应用程序时-您使用相同的种子值-因此您的结果当然是相同的(正如 Martin York 在对该问题的评论中已经提到的那样)。

实际上,您应该调用srand(seed)一次,然后调用rand() 多次并分析该序列-它应该看起来是随机的。

修正 1 - 示例代码:

好的我明白了。显然口头描述是不够的(可能是语言障碍之类的...... :))。

srand()/rand()/time()基于问题中使用的相同函数的老式 C 代码示例:

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

int main(void)
{
    unsigned long j;
    srand( (unsigned)time(NULL) );

    for( j = 0; j < 100500; ++j )
    {
        int n;

        /* skip rand() readings that would make n%6 non-uniformly distributed
          (assuming rand() itself is uniformly distributed from 0 to RAND_MAX) */
        while( ( n = rand() ) > RAND_MAX - (RAND_MAX-5)%6 )
        { /* bad value retrieved so get next one */ }

        printf( "%d,\t%d\n", n, n % 6 + 1 );
    }

    return 0;
}

^^^次运行的程序应该看起来是随机的。

请注意,出于下面解释的原因,我不建议在生产中使用rand/srand函数,并且我绝对不建议将函数time用作随机种子,因为 IMO 已经很明显了。这些对于教育目的很好,有时也可以说明这一点,但对于任何严肃的用途,它们大多是无用的。

修正案 2 - 详细说明:

重要的是要理解,到目前为止,还没有C 或 C++ 标准特性(库函数或类)最终确定地产生实际随机数据(即由标准保证实际上是随机的)。解决这个问题的唯一标准特性是std::random_device,遗憾的是它仍然不能保证实际随机性。

根据应用程序的性质,您应该首先确定您是否真的需要真正随机(不可预测的)数据。当你确实需要真正的随机性时,值得注意的情况是信息安全——例如生成对称密钥、非对称私钥、盐值、安全令牌等。

然而,安全级随机数是一个独立的行业,值得单独写一篇文章。我在我的这个答案中简要讨论了它们。

在大多数情况下,伪随机数生成器就足够了——例如用于科学模拟或游戏。在某些情况下,甚至需要一致定义的伪随机序列——例如在游戏中,您可以选择在运行时生成完全相同的地图,以避免在您的分布中存储大量数据。

最初的问题和反复出现的大量相同/相似的问题(甚至许多被误导的“答案”)表明,首先重要的是区分随机数和伪随机数,并了解什么是伪随机数序列首先并要意识到伪随机数生成器的使用方式与使用真随机数生成器的方式不同。

直观地,当您请求随机数时 - 返回的结果不应依赖于先前返回的值,不应依赖于之前是否有人请求过任何东西,也不应依赖于什么时候、通过什么过程、在什么计算机上、来自什么生成器和在它被要求的星系。毕竟,这就是“随机”这个词的含义——不可预测且独立于任何事物——否则它不再是随机的,对吧?有了这种直觉,在网络上搜索一些魔法咒语以在任何可能的情况下获得这样的随机数是很自然的。

^^^这种直观的期望在涉及伪随机数生成器的所有情况下都是非常错误和有害的——尽管对于真正的随机数是合理的。

虽然存在“随机数”的有意义的概念(有点) - 没有“伪随机数”这样的东西。伪随机数生成器实际上产生伪随机数序列

伪随机序列实际上总是确定性的(由它的算法和初始参数决定)——也就是说,它实际上没有任何随机性。

当专家谈论 PRNG 的质量时,他们实际上谈论的是生成序列(及其显着的子序列)的统计特性。例如,如果您通过轮流使用它们来组合两个高质量的 PRNG - 您可能会产生不好的结果序列 - 尽管它们分别生成好的序列(这两个好的序列可能只是相互关联,因此组合不好)。

具体来说rand()/srand(s)一对函数提供了一个单一的每进程非线程安全(!)伪随机数序列,使用实现定义的算法生成。函数rand()产生范围内的值[0, RAND_MAX]

引用 C11 标准 (ISO/IEC 9899:2011):

srand函数使用该参数作为一个新的伪随机数序列的种子,这些伪随机数将由后续调用返回rand。如果 srand然后以相同的种子值调用,则应重复伪随机数序列。如果rand在进行任何调用之前调用srand,则应生成与srand第一次调用时相同的序列,种子值为 1。

许多人合理地期望这rand()将产生一系列半独立均匀分布的数字,范围0RAND_MAX。好吧,它当然应该(否则它没用),但不幸的是,不仅标准不需要这样做 - 甚至还有明确的免责声明指出“无法保证产生的随机序列的质量”。在某些历史案例rand/srand实施中确实质量很差。即使在现代实现中它很可能已经足够好 - 但信任被打破并且不容易恢复。除了它的非线程安全特性之外,它在多线程应用程序中的安全使用也变得棘手和有限(仍然可能——您可以只从一个专用线程中使用它们)。

新的类模板std::mersenne_twister_engine<>(及其便利的 typedefs - std::mt19937/std::mt19937_64具有良好的模板参数组合)提供了在 C++11 标准中定义的每个对象的伪随机数生成器。使用相同的模板参数和相同的初始化参数,不同的对象将在使用符合 C++11 标准库的任何应用程序中的任何计算机上生成完全相同的每个对象输出序列。此类的优势在于其可预测的高质量输出序列和跨实现的完全一致性。

在 C++11 标准中还定义了更多 PRNG 引擎 - std::linear_congruential_engine<>(历史上在某些 C 标准库实现中用作公平质量srand/rand算法)和std::subtract_with_carry_engine<>。它们还生成完全定义的参数相关的每个对象输出序列。

上面过时的 C 代码的现代 C++11 示例替换:

#include <iostream>
#include <chrono>
#include <random>

int main()
{
    std::random_device rd;
    // seed value is designed specifically to make initialization
    // parameters of std::mt19937 (instance of std::mersenne_twister_engine<>)
    // different across executions of application
    std::mt19937::result_type seed = rd() ^ (
            (std::mt19937::result_type)
            std::chrono::duration_cast<std::chrono::seconds>(
                std::chrono::system_clock::now().time_since_epoch()
                ).count() +
            (std::mt19937::result_type)
            std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::high_resolution_clock::now().time_since_epoch()
                ).count() );

    std::mt19937 gen(seed);

    for( unsigned long j = 0; j < 100500; ++j )
    /* ^^^Yes. Generating single pseudo-random number makes no sense
       even if you use std::mersenne_twister_engine instead of rand()
       and even when your seed quality is much better than time(NULL) */    
    {
        std::mt19937::result_type n;
        // reject readings that would make n%6 non-uniformly distributed
        while( ( n = gen() ) > std::mt19937::max() -
                                    ( std::mt19937::max() - 5 )%6 )
        { /* bad value retrieved so get next one */ }

        std::cout << n << '\t' << n % 6 + 1 << '\n';
    }

    return 0;
}

使用std::uniform_int_distribution<>的先前代码的版本

#include <iostream>
#include <chrono>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937::result_type seed = rd() ^ (
            (std::mt19937::result_type)
            std::chrono::duration_cast<std::chrono::seconds>(
                std::chrono::system_clock::now().time_since_epoch()
                ).count() +
            (std::mt19937::result_type)
            std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::high_resolution_clock::now().time_since_epoch()
                ).count() );

    std::mt19937 gen(seed);
    std::uniform_int_distribution<unsigned> distrib(1, 6);

    for( unsigned long j = 0; j < 100500; ++j )
    {
        std::cout << distrib(gen) << ' ';
    }

    std::cout << '\n';
    return 0;
}
于 2012-11-19T00:09:42.257 回答
16

每当您使用 C++ 编程语言进行基本的网络搜索时,random number generation通常会首先出现这个问题!我想把我的帽子扔进戒指,希望更好地阐明 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...

因此,如果您想要一个好的数字序列,那么您必须为 PRNG 提供充足的种子!

旧 C 方式

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;
}

C 的 PRNG 的常见用法包含一系列问题,例如:

  1. 的整体界面std::rand()对于在给定范围之间正确生成伪随机数不是很直观,例如,按照@Predictability 想要的方式生成 [1, 6] 之间的数字。
  2. 由于鸽洞原理,的常见用法std::rand()消除了伪随机数均匀分布的可能性。
  3. std::rand()通过技术播种的常见方式std::srand( ( unsigned int )std::time( nullptr ) )是不正确的,因为time_t被认为是受限制的类型。因此,不能保证time_t从to的转换!unsigned int

有关使用 C 的 PRNG 的总体问题以及如何规避这些问题的更多详细信息,请参阅使用 rand() (C/C++):对 C 标准库的 rand() 函数的建议

标准 C++ 方式

自 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;
}

在上面的示例中使用了具有整数值均匀分布的32 位Mersenne Twister引擎。(源代码中引擎的名称听起来很奇怪,因为它的名称来自它的 2^19937-1时期)。该示例还使用种子引擎,该引擎从操作系统获取其值(如果您使用的是 Linux 系统,则从 中返回一个值)。std::random_devicestd::random_device/dev/urandom

请注意,您不必使用任何引擎std::random_device播种。您可以使用常量甚至库!您也不必使用 32 位版本的引擎,还有其他选择!有关该库功能的更多信息,请参阅cplusplus.comchronostd::mt19937random

总而言之,C++ 程序员不应该再使用std::rand()了,不是因为它不好,而是因为当前标准提供了更好的替代方案,更直接、更可靠。希望你们中的许多人都觉得这很有帮助,尤其是那些最近在网上搜索过的人generating random numbers in c++

于 2020-06-14T22:21:36.337 回答
12

如果您使用的是boost库,您可以通过以下方式获得随机生成器:

#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;
    }
}

该函数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);
    }
};
于 2015-02-03T17:07:06.437 回答
9
#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;
}

http://en.cppreference.com/w/cpp/numeric/random/rand

于 2015-01-13T22:16:04.263 回答
5

可以Randomer从这里获得用于生成随机数的完整类代码!

如果您在项目的不同部分需要随机数,您可以创建一个单独的类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_);
    }
};

这样的类以后会很方便:

int main() {
    Randomer randomer{0, 10};
    std::cout << randomer() << "\n";
}

您可以查看此链接作为示例,我如何使用此类Randomer生成随机字符串。Randomer如果您愿意,也可以使用。

于 2018-12-21T15:57:28.803 回答
3

每次生成不同的随机数,而不是连续六次相同的随机数。

用例场景

我将Predictability 的问题比作一袋六张纸,每张纸上都写有0 到5 的值。每次需要新值时,都会从袋子中抽出一张纸。如果袋子是空的,则将数字放回袋子中。

...由此,我可以创建一种算法。

算法

一个包通常是一个Collection. 我选择了一个bool[](也称为布尔数组、位平面或位图)来扮演包的角色。

我之所以选择a bool[],是因为每一项的索引已经是每张纸的价值。如果文件需要写在上面的任何其他内容,那么我会使用 aDictionary<string, bool>来代替。布尔值用于跟踪数字是否已被绘制。

一个被调用的计数器RemainingNumberCount被初始化为5在选择一个随机数时倒计时。这使我们不必在每次希望绘制新数字时计算还剩下多少张纸。

为了选择下一个随机值,我使用 afor..loop来扫描索引包,并在调用anindex时使用计数器来计数。falseNumberOfMoves

NumberOfMoves用于选择下一个可用号码。NumberOfMoves首先设置为0和之间的随机值5,因为我们可以通过袋子进行 0..5 个可用步骤。在下一次迭代NumberOfMoves中,设置为 和 之间的随机值04因为现在我们可以通过袋子进行 0..4 步。随着数字的使用,可用数字减少,因此我们改为使用rand() % (RemainingNumberCount + 1)来计算 的下一个值NumberOfMoves

NumberOfMoves计数器达到零时,for..loop应该如下:

  1. 将当前值设置为与for..loop的索引相同。
  2. 将袋子中的所有数字设置为false
  3. for..loop.

代码

上述解决方案的代码如下:

(将以下三个块依次放入主 .cpp 文件中)

#include "stdafx.h"
#include <ctime> 
#include <iostream>
#include <string>

class RandomBag {
public:
    int Value = -1;

    RandomBag() {
        ResetBag();

    }

    void NextValue() {
        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        int NumberOfMoves = rand() % (RemainingNumberCount + 1);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            if (BagOfNumbers[i] == 0) {
                NumberOfMoves--;

                if (NumberOfMoves == -1)
                {
                    Value = i;

                    BagOfNumbers[i] = 1;

                    break;

                }

            }



        if (RemainingNumberCount == 0) {
            RemainingNumberCount = 5;

            ResetBag();

        }
        else            
            RemainingNumberCount--; 

    }

    std::string ToString() {
        return std::to_string(Value);

    }

private:
    bool BagOfNumbers[6]; 

    int RemainingNumberCount;

    int NumberOfMoves;

    void ResetBag() {
        RemainingNumberCount = 5;

        NumberOfMoves = rand() % 6;

        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            BagOfNumbers[i] = 0;

    }

};

控制台类

我创建了这个 Console 类,因为它可以很容易地重定向输出。

在下面的代码...

Console::WriteLine("The next value is " + randomBag.ToString());

……可以换成……

std::cout << "The next value is " + randomBag.ToString() << std::endl; 

...然后Console可以根据需要删除此类。

class Console {
public:
    static void WriteLine(std::string s) {
        std::cout << s << std::endl;

    }

};

主要方法

示例用法如下:

int main() {
    srand((unsigned)time(0)); // Initialise random seed based on current time

    RandomBag randomBag;

    Console::WriteLine("First set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nSecond set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nThird set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nProcess complete.\n");

    system("pause");

}

示例输出

当我运行程序时,我得到以下输出:

First set of six...

The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1

Second set of six...

The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5

Third set of six...

The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1

Process complete.

Press any key to continue . . .

结束语

该程序是使用Visual Studio 2017编写的,我选择Visual C++ Windows Console Application使用.Net 4.6.1.

我在这里没有做任何特别的事情,所以代码也应该适用于早期版本的 Visual Studio。

于 2017-11-07T11:33:08.333 回答
3

此代码产生从n到 的随机数m

int random(int from, int to){
    return rand() % (to - from + 1) + from;
}

例子:

int main(){
    srand(time(0));
    cout << random(0, 99) << "\n";
}
于 2018-07-07T10:24:37.167 回答
2

这是一个解决方案。创建一个返回随机数的函数并将其放在主函数之外以使其全局化。希望这可以帮助

#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
    srand((unsigned)time(0));
    int die1;
    int die2;
    for (int n=10; n>0; n--){
    die1 = rollDie();
    die2 = rollDie();
    cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
    return (rand()%6)+1;
}
于 2014-05-08T20:44:16.533 回答
1

随机每个 RUN 文件

size_t randomGenerator(size_t min, size_t max) {
    std::mt19937 rng;
    rng.seed(std::random_device()());
    //rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);

    return dist(rng);
}
于 2016-02-01T11:49:41.910 回答
0

我知道如何在不使用任何头文件、编译器内在函数或其他任何东西的情况下在 C++ 中生成随机数。

#include <cstdio> // Just for printf
int main() {
    auto val = new char[0x10000];
    auto num = reinterpret_cast<unsigned long long>(val);
    delete[] val;
    num = num / 0x1000 % 10;
    printf("%llu\n", num);
}

运行一段时间后,我得到了以下统计信息:

0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343

看起来很随意。

这个怎么运作:

  • 现代编译器使用ASLR(地址空间布局随机化)保护您免受缓冲区溢出。
  • 所以你可以在不使用任何库的情况下生成一些随机数,但这只是为了好玩。不要像那样使用 ASLR。
于 2020-12-24T17:41:39.730 回答
-2

这是一个简单的随机生成器,大约。在 0 附近产生正值和负值的概率相等:

  int getNextRandom(const size_t lim) 
  {
        int nextRand = rand() % lim;
        int nextSign = rand() % lim;
        if (nextSign < lim / 2)
            return -nextRand;
        return nextRand;
  }


   int main()
   {
        srand(time(NULL));
        int r = getNextRandom(100);
        cout << r << endl;
        return 0;
   }
于 2018-06-13T13:06:48.513 回答