草庐IT

c++ - 为什么不直接使用 random_device?

coder 2023-06-02 原文

我对 c++11 随机库有点困惑。

我的理解:我们需要两个独立的概念:

  • 随机引擎,可以是:
    • 伪(需要种子)又名 PRNG
    • 真正的随机数生成器
  • 分布:它将从引擎获得的数字映射到特定的区间,使用特定的分布。

我不明白为什么不直接使用真正的随机数生成器:

std::random_device rd;
std::uniform_int_distribution<int> dist(1, 5);

// get random numbers with:
dist(rd);

据我所知,这很好用。

相反,这是我在大多数示例/网站/文章中发现的:

std::random_device rd;
std::mt19937 e{rd()}; // or std::default_random_engine e{rd()};
std::uniform_int_distribution<int> dist{1, 5};

// get random numbers with:
dist(e);

我不是在谈论特殊用途,例如密码学,只是您的基本入门文章。

我的怀疑是因为 std::mt19937(或 std::default_random_engine)接受种子,在调试期间提供相同的种子可以更容易调试 session 。

另外,为什么不只是:

std::mt19937 e{std::random_device{}()};

最佳答案

Also, why not just:

std::mt19937 e{std::random_device{}()};

如果您只执行一次可能会很好,但如果您会执行多次,最好跟踪您的std::random_device而不是不必要地创建/销毁它。

查看 libc++ 源代码以实现 std::random_device 可能会有所帮助,这很简单。它只是 std::fopen("/dev/urandom") 上的一个薄包装.所以每次创建 std::random_device您将获得另一个文件系统句柄,并支付所有相关费用。

据我所知,在 Windows 上,std::random_device表示对 Microsoft 加密 API 的一些调用,因此每次执行此操作时都将初始化和销毁​​一些加密库接口(interface)。

这取决于您的应用程序,但出于一般目的,我不会认为这种开销总是可以忽略不计。有时确实如此,然后这很棒。

我想这与您的第一个问题有关:

Instead, this is what I found on most examples/sites/articles:

 std::random_device rd;
 std::mt19937 e{rd()}; // or std::default_random_engine e{rd()};
 std::uniform_int_distribution<int> dist{1, 5};

至少我是这么想的:

  • std::mt19937是一个非常简单可靠的随机发生器。它是独立的,将完全存在于您的进程中,而不需要调用操作系统或其他任何东西。该实现是标准强制,至少在 boost 中,它在任何地方都使用相同的代码,源自原始 mt19937纸。这段代码非常稳定并且是跨平台的。您可以非常自信地对其进行初始化、查询等操作将在您编译它的任何平台上编译为类似的代码,并且您将获得类似的性能。

  • std::random_device相比之下是相当不透明的。你并不确切知道它是什么,它会做什么,或者它的效率如何。你甚至不知道它是否真的可以被获取——当你尝试创建它时它可能会抛出一个异常。你知道它不需要种子。您通常不应该从中提取大量数据,只需使用它来生成种子。有时,它作为加密 API 的一个很好的接口(interface),但实际上并不需要这样做,遗憾的是有时它不需要。它可能对应于 /dev/random在 unix 上,它可能对应于 /dev/urandom/ .它可能对应于一些 MSVC 加密 API (visual studio),或者它可能只是一个固定常量 (mingw)。如果您为某些手机进行交叉编译,谁知道它会做什么。 (即使您确实得到了 /dev/random ,您仍然会遇到性能可能不一致的问题一致 - 它可能看起来工作得很好,直到熵池用完,然后运行缓慢作为一条狗。)

我的想法是,std::random_device应该是像 time(NULL) 播种的改进版本-- 这是一个低标准,因为 time(NULL)考虑到所有因素,它都是一个非常糟糕的种子。我通常在我会使用 time(NULL) 的地方使用它回到过去,产生种子。除此之外,我真的认为它并没有什么用处。

关于c++ - 为什么不直接使用 random_device?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39288595/

有关c++ - 为什么不直接使用 random_device?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  8. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

随机推荐