“cpp/numeric/random/seed seq/generate”的版本间的差异

来自cppreference.com
< cpp‎ | numeric‎ | random‎ | seed seq
(1个修订: Translate from the English version)
 
(未显示7个用户的9个中间版本)
第1行: 第1行:
{{tr_note}}
+
{{cpp/numeric/random/seed_seq/title|generate}}
{{cpp/numeric/random/seed_seq/title | generate}}
+
 
{{cpp/numeric/random/seed_seq/navbar}}
 
{{cpp/numeric/random/seed_seq/navbar}}
{{ddcl list begin}}
+
{{ddcl|sincec++11|1=
{{ddcl list item | notes={{mark since c++11}} | 1=
+
 
template< class RandomIt >
 
template< class RandomIt >
 
void generate( RandomIt begin, RandomIt end );
 
void generate( RandomIt begin, RandomIt end );
 
}}
 
}}
{{ddcl list end}}
 
  
{{tr| 无符号整数 值填充 范围 {{c|[begin, end)}}{{tt|i}},{{math|0 ≤ i < 2{{su|p=32}}}},根据最初提供 数据,在这{{tt|seed_seq}}的构造函数。所产 的值的分布在整个32位的范围内,即使初始值被强烈的 见.|Fills the range {{c|[begin, end)}} with unsigned integer values {{tt|i}}, {{math|0 ≤ i < 2{{su|p=32}}}}, based on the data originally provided in the constructor of this {{tt|seed_seq}}. The produced values are distributed over the entire 32-bit range even if the initial values were strongly biased.}}
+
{{|无符号整数值填充范围 {{|beginend}} 的 生 偏
 +
{{c|begin end}} {{|}}
 +
  
{{tr| 。使用下面的算法(改编自梅森难题发生器的初始化序列,[http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html Makoto Matsumoto and Takuji Nishimura]纳入由[http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf Mutsuo Saito in 2007]改进)。|The following algorithm is used (adapted from the initialization sequence of the Mersenne Twister generator by [http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html Makoto Matsumoto and Takuji Nishimura], incorporating the improvements made by [http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf Mutsuo Saito in 2007])}}
+
{{|::::}}
  
* {{tr|。 如果{{c|1=begin == end}} ,什么也 做。否则,。|If {{c|1=begin == end}}, do nothing. Otherwise,}}
+
如果 {{|}} 不 {{|}}
  
* {{tr| 。首先,每个元素的输出范围设置的 值{{c|0x8b8b8b8b}} |First, set each element of the output range to the value {{c|0x8b8b8b8b}}}}
+
 +
 +
 +
{{|值
 +
{{c|}}|
 +
 +
,
 +
{{c|}}
 +
 +
 +
 +
 +
 +
 +
}}
  
* {{tr| 。变换的输出范围内的元素 根据以下算法:。|Transform the elements of the output range according to the following algorithm:}}
+
{{|,|}}
  
For {{c|1=k = 0,..., m-1}}<br>
+
{{c|}}
  
{{tr| 。地方{{c|1=m=max(s+1, n)}}<br>。|where {{c|1=m=max(s+1, n)}}<br>}}
+
{{||m}} 的 数 {{c|k}}
and {{c|1=n=begin-end}}<br>
+
and {{c|1=s=v.size()}}<br>
+
{{tr|。 {{c|v}}是最初提供 值这{{tt|seed_seq}}对象的构造函 ,私营集装箱控股。|and {{c|v}} is the private container holding the values originally provided by the constructor of this {{tt|seed_seq}} object,}}
+
# {{c|1=begin[k+p] += r1}}
+
# {{c|1=begin[k+q] += r2}}
+
# {{c|1=begin[k] = r2}},
+
{{tr|。地方{{c|1=p=(n-t)/2}}<br>。|where {{c|1=p=(n-t)/2}}<br>}}
+
and {{c|1=q=p+t}}<br>
+
and {{c|1=t=(n >= 623) ? 11 : (n >= 68) ? 7 : (n >= 39) ? 5 : (n >= 7) ? 3 : (n - 1) / 2 }}<br>
+
and {{c|1=r1=1664525 * T(begin[k]^begin[k+p]^begin[k−1])}}<br>
+
and {{c|1=T(x) = x ^ (x << 27)}}<br>
+
and {{c|1=r2=r1+s}} if {{c|1=k==0}}, {{c|1=r2=r1 + k%n + v[k-1]}} if {{c|1=0<k<=s}}, {{c|1=r2=r1 + k%n}} if {{c|1=k>s}}.
+
  
For {{c|1=k = m,..., m+n-1}},
+
{{|=1}}{{|k+p}}{1}{{|=k}} {{|=k+p}} {{|=k-1}}}}
# {{c|1=begin[k+p] ^= r3}}
+
# {{c|1=begin[k+q] ^= r4}}
+
# {{c|1=begin[k]=r4}}
+
{{tr| 。地方{{c|1=r3 = 1566083941 * T(begin[k]+begin[k+p]+begin[k-1])}}<br>。|where {{c|1=r3 = 1566083941 * T(begin[k]+begin[k+p]+begin[k-1])}}<br>}}
+
and {{c|1=r4=r3 - k%n}}
+
  
{{tr| 。所有的计算都进行{{math|modulo 2{{su|p=32}}}}{{c|begin[x]}} 的索引输出范围({{math|modulo n}} )的.|where all calculations are performed {{math|modulo 2{{su|p=32}}}} and where the indexing of the output range ({{c|begin[x]}}) is taken {{math|modulo n}}.}}
+
{{|{{|2{{su|=}}}} {{|}}
 +
{{|}} {{|2
 +
{{su|=}}}} {{|}}
 +
{{|n}} }}
  
===。参数。===
+
{{} |{{| {{|}} |{{|}}{{}}{{|}}}}
{{param list begin}}
+
{{param list item | begin, end |{{tr。可变随机访问迭代器,其{{c|std::iterator_traits<>::value_type}} 是一个无符号的整数类型,适合用于存储32位值。| mutable random-access iterators whose {{c|std::iterator_traits<>::value_type}} is an unsigned integer type suitable for storing 32-bit values}}}}
+
{{param list hreq}}
+
{{param list req concept | RandomIt | RandomAccessIterator}}
+
{{param list end}}
+
  
===。
+
{{|{{|}}|{{|) }}}}
  返回值。===
+
{{tr| 。没有,结果被写入到{{c|[begin, end)}} 范围.|none, the results are written to the {{c|[begin, end)}} range.}}
+
  
===。为 。===
+
===。
 +
 
 +
 +
 
 +
为 。
 +
 
 +
 +
 
 +
 +
 
 +
 +
 
 +
 +
 
 +
 +
 +
 +
 +
 
 +
 +
 +
 
 +
===
 
{{example
 
{{example
|
+
|code=
| code=
+
#include <
#include <random>
+
 +
>
 
#include <iostream>
 
#include <iostream>
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
  
 
int main()
 
int main()
 
{
 
{
     std::seed_seq seq({1,2,3,4,5});
+
     std::{1, 2, 3, 4, 5}
     std::vector<std::uint32_t> seeds(10);
+
 +
 +
 +
);
 +
     std::vector<std::uint32_t> seeds();
 
     seq.generate(seeds.begin(), seeds.end());
 
     seq.generate(seeds.begin(), seeds.end());
// Step 1: fill with 0x8b8b8b8b
+
     for (std::uint32_t n : seeds)
// seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251,
+
//          2341178251, 2341178251, 2341178251, 2341178251, 2341178251 }
+
//
+
// Step 2:
+
// n = 10, s = 5, t = 3, p = 3, q = 6, m = 10
+
//
+
// First iteration, k = 0; r1 = 1371501266, r2 = 1371501271
+
//
+
// seeds = {1371501271, 2341178251, 2341178251, 3712679517, 2341178251,
+
//          2341178251, 3712679522, 2341178251, 2341178251, 2341178251 }
+
//
+
// Iterations from k = 1 to k = 5 (r2 = r1 + k%n + v[k-1])
+
//
+
// r1 = 2786190137, 3204727651, 4173325571, 1979226628, 401983366
+
// r2 = 2786190139, 3204727655, 4173325577, 1979226636, 401983376
+
//
+
// seeds = {3350727907, 3188173515, 3204727655, 4173325577, 1979226636,
+
//          401983376, 3591037797, 2811627722, 1652921976, 2219536532 }
+
//
+
// Iterations from k = 6 to k = 9 (r2 = r1 + k%n)
+
//
+
// r1 = 2718637909, 1378394210, 2297813071, 1608643617
+
// r2 = 2718637915, 1378394217, 2297813079, 1608643626
+
//
+
// seeds = { 434154821, 1191019290, 3237041891, 1256752498, 4277039715,
+
//          2010627002, 2718637915, 1378394217, 2297813079, 1608643626 }
+
//
+
// Step 3
+
// iterations from k = 10 to k = 19, using ^= to modify the output
+
//
+
// r1 = 1615303485, 3210438310, 893477041, 2884072672, 1918321961,
+
// r2 = 1615303485, 3210438309, 893477039, 2884072669, 1918321957
+
//
+
// seeds = { 303093272, 3210438309,  893477039, 2884072669, 1918321957,
+
//          1117182731, 1772877958, 2669970405, 3182737656, 4094066935 }
+
//
+
// r1 =  423054846, 46783064, 3904109085, 1534123446, 1495905687
+
// r2 =  423054841, 46783058, 3904109078, 1534123438, 1495905678
+
//
+
// seeds = { 4204997637, 4246533866, 1856049002, 1129615051, 690460811,
+
//          1075771511,  46783058, 3904109078, 1534123438, 1495905678 }
+
 
+
     for(std::uint32_t n : seeds)
+
 
         std::cout << n << '\n';
 
         std::cout << n << '\n';
 +
 +
 +
 +
 +
 +
 +
 
}
 
}
| output=
+
|output=
 
4204997637
 
4204997637
 
4246533866
 
4246533866
第125行: 第208行:
 
1495905678  
 
1495905678  
 
}}
 
}}
 +
 +
 +
 +
 +
 +
 +

2024年10月23日 (三) 19:39的最后版本

 
 
 
 
 
template< class RandomIt >
void generate( RandomIt begin, RandomIt end );
(C++11 起)

基于 v 中存储的(可能有偏差的)种子,通过以 32 位无符号整数值填充范围 [beginend) 的方式生成无偏差种子。

  • 如果 begin == endtrue,那么什么也不做。
  • 否则,按照如下所述的生成算法生成种子。

如果 std::iterator_traits<RandomIt>::value_type 不是无符号整数类型,或者它的宽度小于 32,那么程序非良构。

如果 RandomIt 不满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求,或者它不可变,那么行为未定义。

目录

[编辑] 生成算法

给定以下值和操作:

定义
z v .size()
n end - begin
m std::max(z + 1, n)
t (n >= 623) ? 11 : (n >= 68) ? 7 : (n >= 39) ? 5 : (n >= 7) ? 3 : (n - 1) / 2
p (n - t) / 2
q p + t
操作 定义
xor 内建的逐位异或
rshift 内建的向右移位
T(x) x xor (x rshift 27)

生成算法包含以下步骤,其中 Si 表示 begin[i % n]Vi 表示 v [i]

1) 将输出范围中的所有元素都设置为 0x8b8b8b8b
2)[0m) 中的所有整数 k,依次按顺序进行以下操作:
1)r11664525·T(Sk xor Sk+p xor Sk-1)
2)r2r1+j,其中 j 是:
  • z,如果 k=0
  • (k mod n)+Vk-1,如果 0<k⩽z
  • k mod n,如果 z<k
3)Sk+p 设置为 (Sk+p+r1) mod 232
4)Sk+q 设置为 (Sk+q+r2) mod 232
5)Sk 设置为 r2 mod 232
3)[mm + n) 中的所有整数 k,依次按顺序进行以下操作:
1)r31566083941·T(Sk+Sk+p+Sk-1)
2)r4r3-(k mod n)
3)Sk+p 设置为 (Sk+p xor r3) mod 232
4)Sk+q 设置为 (Sk+q xor r4) mod 232
5)Sk 设置为 r4 mod 232

[编辑] 参数

begin, end - 表示输出范围的迭代器

[编辑] 异常

只会抛出在 beginend 上的 RandomIt 操作抛出的异常。

[编辑] 示例

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <random>
 
// std::seed_seq 主体部分的雏形……
struct seed_seq
{
    std::vector<std::uint32_t> v;
 
    seed_seq(std::initializer_list<std::uint32_t> const il) : v{il} {}
 
    template<typename RandomIt>
    void generate(RandomIt first, RandomIt last)
    {
        if (first == last)
            return;
        //
        // 假定 v = {1,2,3,4,5} 且 distance(first, last) == 10。
        //
        // 步骤 1:以 0x8b8b8b8b 填充
        // seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251,
        //          2341178251, 2341178251, 2341178251, 2341178251, 2341178251}
        //
        std::fill(first, last, 0x8b8b8b8b);
        //
        // 步骤 2:
        // n = 10, s = 5, t = 3, p = 3, q = 6, m = 10
        //
        const std::uint32_t n = last - first;
        const std::uint32_t s = v.size();
        const std::uint32_t t = (n < 7) ? (n - 1) / 2
                              : (n < 39) ? 3
                              : (n < 68) ? 5
                              : (n < 623) ? 7
                              : 11;
        const std::uint32_t p = (n - t) / 2;
        const std::uint32_t q = p + t;
        const std::uint32_t m = std::max(s + 1, n);
        //
        // 首次迭代,k = 0;r1 = 1371501266,r2 = 1371501271
        //
        // seeds = {1371501271, 2341178251, 2341178251, 3712679517, 2341178251,
        //          2341178251, 3712679522, 2341178251, 2341178251, 2341178251}
        //
        // 从 k = 1 到 k = 5 迭代(r2 = r1 + k % n + v[k - 1])
        //
        // r1 = 2786190137, 3204727651, 4173325571, 1979226628, 401983366
        // r2 = 2786190139, 3204727655, 4173325577, 1979226636, 401983376
        //
        // seeds = {3350727907, 3188173515, 3204727655, 4173325577, 1979226636,
        //           401983376, 3591037797, 2811627722, 1652921976, 2219536532}
        //
        // 从 k = 6 到 k = 9 迭代(r2 = r1 + k % n)
        //
        // r1 = 2718637909, 1378394210, 2297813071, 1608643617
        // r2 = 2718637915, 1378394217, 2297813079, 1608643626
        //
        // seeds = { 434154821, 1191019290, 3237041891, 1256752498, 4277039715,
        //          2010627002, 2718637915, 1378394217, 2297813079, 1608643626}
        //
        auto begin_mod = [first, n](std::uint32_t u) -> decltype(*first)&
        {
            return first[u % n]; // 即 begin[x] 按 modulo n 取值
        };
        auto T = [](std::uint32_t x) { return x ^ (x >> 27); };
 
        for (std::uint32_t k = 0, r1, r2; k < m; ++k)
        {
            r1 = 1664525 * T(begin_mod(k) ^ begin_mod(k + p) ^ begin_mod(k - 1));
            r2 = (k == 0) ? r1 + s
               : (k <= s) ? r1 + k % n + v[k - 1]
               :            r1 + k % n;
            begin_mod(k + p) += r1;
            begin_mod(k + q) += r2;
            begin_mod(k) = r2;
        }
        //
        // 步骤 3
        // 从 k = 10 到 k = 19 迭代,用 ^= 修改输出
        //
        // r1 = 1615303485, 3210438310, 893477041, 2884072672, 1918321961,
        // r2 = 1615303485, 3210438309, 893477039, 2884072669, 1918321957
        //
        // seeds = { 303093272, 3210438309,  893477039, 2884072669, 1918321957,
        //          1117182731, 1772877958, 2669970405, 3182737656, 4094066935}
        //
        // r1 =  423054846, 46783064, 3904109085, 1534123446, 1495905687
        // r2 =  423054841, 46783058, 3904109078, 1534123438, 1495905678
        //
        // seeds = { 4204997637, 4246533866, 1856049002, 1129615051, 690460811,
        //           1075771511,   46783058, 3904109078, 1534123438, 1495905678}
        //
        for (std::uint32_t k = m, r3, r4; k < m + n; ++k)
        {
            r3 = 1566083941 * T(begin_mod(k) + begin_mod(k + p) + begin_mod(k - 1));
            r4 = r3 - k % n;
            begin_mod(k+p) ^= r3;
            begin_mod(k+q) ^= r4;
            begin_mod(k) = r4;
        }
    }
};
 
int main()
{
    const auto input = std::initializer_list<std::uint32_t>{1, 2, 3, 4, 5};
    const auto output_size = 10;
 
    // 使用 std 版本的 seed_seq
    std::seed_seq seq(input);
    std::vector<std::uint32_t> seeds(output_size);
    seq.generate(seeds.begin(), seeds.end());
    for (const std::uint32_t n : seeds)
        std::cout << n << '\n';
 
    // 使用自定义版本的 seed_seq
    seed_seq seq2(input);
    std::vector<std::uint32_t> seeds2(output_size);
    seq2.generate(seeds2.begin(), seeds2.end());
 
    assert(seeds == seeds2);
}

输出:

4204997637
4246533866
1856049002
1129615051
690460811
1075771511
46783058
3904109078
1534123438
1495905678

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 2180 C++11 seed_seq::generate 不会抛出异常 它可以抛出异常