English 中文(简体)
使用经营者”到种子mt19937
原标题:Using operator>> to seed mt19937

https://www.pcg-random.org/posts/cpp-seeding-surprises.html Seeding Surprises, “ Melissa E. O Neill” reports that, “When std:seed_seq 试图“确定”高质量的种子数据,实际上使数据恶化。 据O Neill说,真正的随机种子使所有国家成为可能,但如果你通过<条码>推动这种种子:种子-seq,则这种种子变得不那么随意,某些国家通过种子无法取得。

因此,如果你有良好的外围来源,那么为什么不绕过<条码>,就完全照相_seq?

这一条的功能如下:<代码>。 摘自我的rand_replacement Deposit。 它使用<代码>operator>>,在mt19937中超过所有624个国家变量。

template <typename ResultType>
class rand_replacement
{
public:
    using urbg_type = std::mt19937;
    using seed_type = typename std::mt19937::result_type;
private:
    urbg_type eng_{ seed_type{1u} };  // By default, rand() uses seed 1u.

    // ...

    void seed_randomly()
    {
        std::random_device rd;
        std::stringstream ss;
        for (auto i{ std::mt19937::state_size }; i--;)
            ss << rd() <<    ;
        ss >> eng_;
    }
};

这是一种新颖和有趣的想法,还是真的 f?

关于<代码>std:stringstream: 我的理解是,这相对缓慢,但这种征兆是这样。 提单应当是经常操作。

关于<代码>std:random_device: 我的理解是,random_device<>/code> 在某些制度中可能是决定性的,可能会阻挡其他系统,而且它有一个带有GW光的经过核实的历史,但现在至少我对此感到满意。 我的问题并不涉及<代码> random_device;它严格侧重于通过 Seed_seq, 采用operator>>, 一种可用于任何热带来源的技术。

是否有任何下滑?

这样,使用<条码>种子_seq的备选案文就更加复杂,并像以下一些内容。 难道这比我上文阐述的更好选择吗?

    void seed_randomly()
    {
        std::random_device rd;
        std::array<seed_type, std::mt19937::state_size> seeds;
        for (auto& s : seeds)
            s = rd();
        std::seed_seq const sseq{ std::cbegin(seeds), std::cend(seeds) };
        eng_.seed(sseq);
    }
最佳回答

这里得出的结论是,最好绕过<条码>:见d_seq。 当你拥有真正随机的原始数据来源时。

关于许多系统,但也许并非所有系统,st:random_device 属于此种来源。 其潜在的陷阱是众所周知的。 这一答案假设,<代码>t:random_device得出的数值确实是随机的。

另一项结论是,使用<代码>operator>>在问题中提出的解决办法是次优。 这一解决办法按现有标准运作,但<代码>的间接费用如下:斯特罗门不必要地放慢。 更好的解决办法是,创建一种直接产生种子的习俗(>>,见d_seq,而不必将其序列化,然后通过std:stringstream

根据@Sam Mason 和@Severin Pappadeux 的想法,我上课,执行<代码>完整接口:见d_seq。

它不使用概念或SFINAE强制执行对其模板论点的任何要求。 除此以外,我认为它符合C++标准界定的种子序列的所有要求。

功能seed_randomly现已成为模板,与C++的任何随机编号发动机合作。 标准图书馆。

More precisely, it works with any random number engine that has a templated member function seed(sseq). If, however, function seed(sseq) is not templated, and instead has its parameter hard-coded as std::seed_seq, then seed_randomly will fail, because it will be unable to convert tbx::seed_seq_rd into std::seed_seq.

I tested with MSVC, and was able to seed all of the engines from the standard library, as well as a couple of PCG implementations I coded myself.

The following is a mini-test program that seeds both std::mt19937 and std::mt19937_64. It is a complete program, so you should be able to copy, paste, and compile without any need to fiddle. I had my compiler set to C++14.

#include <array>             // array
#include <cstddef>           // size_t
#include <initializer_list>  // initializer_list
#include <random>            // mt19937, random_device
#include <iostream>          // cout, ostream_iterator (used only in main)
namespace tbx
{
    class seed_seq_rd
    {
        // This class mimics the interface of std::seed_seq, but 
        // uses std::random_device to generate seeds. 
        //
        // It does not use concepts or SFINAE to enforce any 
        // requirements on its template arguments. Other than that, 
        // it complies with all requirements of a seed sequence as 
        // defined in the C++ standard.
    public:
        using result_type = typename std::random_device::result_type;
    private:
        // No matter what ctor you use, all you get is this array 
        // with one element. Best practice, therefore, is to use the 
        // default ctor.
        enum : std::size_t { zero, one };
        std::array<result_type, one> seeds{};
    public:
        seed_seq_rd() noexcept
            = default;
        template <typename InputIt>
        seed_seq_rd(InputIt begin, InputIt end)
        {}
        template <typename T>
        seed_seq_rd(std::initializer_list<T> li)
        {}
        seed_seq_rd(seed_seq_rd const&)
            = delete;
        seed_seq_rd& operator=(seed_seq_rd const&)
            = delete;
        template <typename RandomIt>
        void generate(RandomIt begin, RandomIt end)
        {
            std::random_device rd;
            while (begin != end)
            {
                *begin = rd();
                ++begin;
            }
        }
        template <typename OutputIt>
        void param(OutputIt dest) const
        {
            *dest = seeds.front();
        }
        auto size() const noexcept
        {
            return seeds.size();
        }
    };

    template <typename RandomEngine>
    void seed_randomly(RandomEngine& e)
    {
        tbx::seed_seq_rd s;
        e.seed(s);
    }
}
int main()
{
    std::mt19937 mt;
    std::cout << "std::mt19937 - Default seeding:
" << mt << "

";

    tbx::seed_randomly(mt);
    std::cout << "std::mt19937 - Random seeding:
" << mt << "

";

    tbx::seed_randomly(mt);
    std::cout << "std::mt19937 - A different random seeding:
" << mt << "

";

    std::mt19937_64 mt64;
    std::cout << "std::mt19937_64 - Default seeding:
" << mt64 << "

";

    tbx::seed_randomly(mt64);
    std::cout << "std::mt19937_64 - Random seeding:
" << mt64 << "

";

    tbx::seed_randomly(mt64);
    std::cout << "std::mt19937_64 - A different random seeding:
" << mt64 << "

";

    // Other ctors work, but there is no reason to use anything 
    // but the default ctor.
    {
        std::array<int, 10> primes{ 1, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
        tbx::seed_seq_rd s(std::cbegin(primes), std::cend(primes));
        std::cout 
            << "tbx::seed_seq_rd - Construct from iterator range:
"
            << "sseq.size(): " << s.size()
            << "
sseq.param(): ";
        s.param(std::ostream_iterator
            <tbx::seed_seq_rd::result_type>(std::cout, " "));
        std::cout << "

";
    }
    {
        tbx::seed_seq_rd s{ -1ll, 0ll, 1ll };
        std::cout 
            << "tbx::seed_seq_rd - Construct from std::initializer_list<long long>:
" 
            << "sseq.size(): " << s.size()
            << "
sseq.param(): ";
        s.param(std::ostream_iterator
            <tbx::seed_seq_rd::result_type>(std::cout, " "));
        std::cout << "

";
    }
    return 0;
}
问题回答




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?