当前位置: 首页 > 知识库问答 >
问题:

通用随机数生成

富勇军
2023-03-14

C++11引入了比C的rand()优越得多的随机数库。在C中,您经常会看到以下代码:

srand(time(0));
rand() % MAX + MIN;

因为time(0)以秒为单位返回当前时间,所以对程序的快速连续调用将产生相同的数字序列。解决这一问题的快速方法是在纳秒内提供一个种子:

 struct timeval time; 
 gettimeofday(&time,NULL);
 srand((time.tv_sec * 1000) + (time.tv_usec / 1000));

在C++11中,我所知道的产生好随机数的最短程序是:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> dist(1, 10);
    std::cout << dist(mt);
}

std::random_device是不可移植的,不鼓励std::default_random_engine使用,因为它可能会选择较差的引擎,如std::rand。事实上,std::random_shuffle不推荐使用,因此首选std::shuffle。通常,我看到人们说用chrono来提供一个种子来代替:

std::chrono::high_resolution_clock::now().time_since_epoch().count()

这不仅很难记住,而且当我们想用纳秒代替时,看起来更难看:

using namespace std::chrono;
std::mt19937 mt(duration_cast<nanoseconds>(high_resolution_clock::now()
                                      .time_since_epoch()).count());

哪种方法是最好的?

共有1个答案

巫马修然
2023-03-14

(1)了解可用的发电机,选择最适合工作的

(2)烹饪种子熵,绘制标准度量值(如256位),打印到日志中

(3)将您的标准种子块转换为一个适合所讨论的发电机大小的seed_seq,并将genny种子化

struct KISS {  uint32_t a, b, c, d; ... };

uint32_t KISS::cycle ()
{
   a = (a & 0xFFFF) * 36969 + (a >> 16);         // 16-bit MWC, a.k.a. znew()
   b = (b & 0xFFFF) * 18000 + (b >> 16);         // 16-bit MWC, a.k.a. wnew()
   c = c * 69069 + 1234567;                      // 32-bit LCG, a.k.a. CONG()(
   d ^= d << 13;  d ^= d >> 17;  d ^= d << 5;    // 32-bit XorShift a.k.a. SHR3(), corrected

   return (((a << 16) | (b & 0xFFFF)) ^ c) + d;  // mixing function (combiner)
}

组合的Tausworthe:

struct LFSR113 {  uint32_t a, b, c, d; ... };

uint32_t LFSR113::cycle ()
{
   a = ((a ^ (a <<  6)) >> 13) ^ ((a & ~0x01) << 18);  // 31 bits
   b = ((b ^ (b <<  2)) >> 27) ^ ((b & ~0x07) <<  2);  // 29 bits
   c = ((c ^ (c << 13)) >> 21) ^ ((c & ~0x0F) <<  7);  // 28 bits
   d = ((d ^ (d <<  3)) >> 12) ^ ((d & ~0x7F) << 13);  // 25 bits

   return a ^ b ^ c ^ d;
}

作为初级生成器,您必须调整禁用种子(粘性状态),但对于种子拉伸(生成seed_seq),这可以安全地忽略。有很多替代方案,比如使用std::vector和一个简单生成器(LCG)来生成一个合适的seed_seq,但我更喜欢尝试过的、可信的和经过彻底分析的解决方案,用最大的bang来实现最少的代码量。

这里所示的两个4x32生成器可以使用中国剩余定理步进,相反,任何状态都可以映射到整个序列中它的唯一点(暂时忽略轨道之类的东西)。这使得它们和其他类似的发电机在不需要XORShift1024*(或mt19937)这样的大枪时,作为一般使用的初级发电机具有吸引力。

#include "zrbj/rng_wrapper.hpp"
#include <random>
#include <typeinfo>

int main ()
{
   zrbj::seeded<std::mt19937> rng(42);

   std::cout << typeid(rng.wrapped_rng).name() << " -> " << rng();
}       

这将生成器、42和实际的种子打印到日志中,除了将比特粉碎成碎片并将它们填入MT19937之外。代码一次,向后靠,享受。

 类似资料:
  • random 生成随机数包 文档:https://www.npmjs.com/package/random 安装:npm install --save random 封装代码: app / extend / context.js // 导入 jwt const jwt = require('jsonwebtoken') // 导入随机数包 const random = require('rando

  • 问题 你需要生成在一定范围内的随机数。 解决方案 使用 JavaScript 的 Math.random() 来获得浮点数,满足 0<=X<1.0 。使用乘法和 Math.floor 得到在一定范围内的数字。 probability = Math.random() 0.0 <= probability < 1.0 # => true # 注意百分位数不会达到 100。从 0 到 100 的范围实

  • 问题内容: 我需要生成一个随机数。 看来该功能已不复存在。 我的选择是, 和 。 我在函数上找不到任何文档,头文件中也没有注释。 问题答案: ===== Swift 4.2 / Xcode 10 ===== 斯威夫特在引擎盖下用来完成工作。 ===== Swift 4.1 / Xcode 9 ===== 返回 0* 到 4294967295之间 的随机数 * 返回 0.0* 到 1.0 范围内的随

  • 在 Java 中要生成一个指定范围之内的随机数字有两种方法:一种是调用 Math 类的 random() 方法,一种是使用 Random 类。 Random 类提供了丰富的随机数生成方法,可以产生 boolean、int、long、float、byte 数组以及 double 类型的随机数,这是它与 random() 方法最大的不同之处。random() 方法只能产生 double 类型的 0~1

  • 我的任务: 生成1到20之间的随机数,小数点后1位。 然而,我的问题就像mt_rand一样简单。我希望大多数生成的数字较低,大约0.5-4.5,偶尔的数字在4.5-10之间,很少说每12-20小时一次在10-20之间。 我一直在使用以下内容,但不知道从哪里开始。我是一个很基本的自学程序员。 也许如果我简单地解释一下为什么我想要这个,它可能会有帮助… 我拥有一个在线游戏,想要添加3个“银行”与每个银

  • 我需要在我的脚本中生成大约5000个随机数,但是CPU速度太快了,我看到了随机数的趋势。 例如,在第一次迭代的100次中,我用rand(0100)得到了80个介于70和99之间的值;,这真的很不方便。 有没有办法解决这样的问题,或者说,在2012年,随机性已经无法实现了? 我相信有可能从一个执行随机次数的函数中生成随机数。。。但我想不出一个。