std::seed_seq::generate

< cpp‎ | numeric‎ | random‎ | seed seq
 
 
数值库
常用数学函数
数学特殊函数 (C++17)
数学常数 (C++20)
浮点环境 (C++11)
复数
数值数组
伪随机数生成
编译时有理数算术 (C++11)
数值算法
(C++17)
(C++17)
插值
(C++20)
(C++20)
通用数值运算
(C++11)
位操作
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
 
 
 
template< class RandomIt >
void generate( RandomIt begin, RandomIt end );
(C++11 起)

以基于最初提供于此 seed_seq 构造函数的无符号整数值 i0 ≤ i < 232
填充范围 [begin, end) 。产生的值分布在整个 32 位范围,即使初值有强偏差。

使用下列算法(改编自松本真与西村拓士发明的梅森缠绕器生成器,加以斋藤睦夫于 2007 的改进工作)。

  • begin == end 则不做任何事。否则,
  • 首先,设置输出范围的每个元素为值 0x8b8b8b8b
  • 按照下列算法变换输出范围的元素:

对于 k = 0,..., m-1

其中 m=max(s+1, n)
n=end-begin
s=v.size()
v 是保有最初为此 seed_seq 对象的构造函数所提供的值的私有容器,

  1. begin[k+p] += r1
  2. begin[k+q] += r2
  3. begin[k] = r2

其中 p=(n-t)/2
q=p+t
t=(n >= 623) ? 11 : (n >= 68) ? 7 : (n >= 39) ? 5 : (n >= 7) ? 3 : (n - 1) / 2
r1=1664525 * T(begin[k]^begin[k+p]^begin[k−1])
T(x) = x ^ (x >> 27)
而若 k==0r2=r1+s ,若 0<k<=sr2=r1 + k%n + v[k-1] ,若 k>sr2=r1 + k%n

对于 k = m,..., m+n-1

  1. begin[k+p] ^= r3
  2. begin[k+q] ^= r4
  3. begin[k]=r4

其中 r3 = 1566083941 * T(begin[k]+begin[k+p]+begin[k-1])
r4=r3 - k%n

其中,所有计算以 modulo 232
进行,并且以 modulo n 取输出范围的下标( begin[x] )。

参数

begin, end - 可变随机访问迭代器,其 std::iterator_traits<>::value_type 为适合存储 32 位值的无符号整数类型
类型要求
-
RandomIt 必须满足遗留随机访问迭代器 (LegacyRandomAccessIterator) 的要求。

返回值

无,写入结果到 [begin, end) 范围。

异常

仅若 beginend 上的操作抛出才抛异常。

示例

#include <random>
#include <iostream>
 
int main()
{
    std::seed_seq seq({1,2,3,4,5});
    std::vector<std::uint32_t> seeds(10);
    seq.generate(seeds.begin(), seeds.end());
// 步骤 1 :以 0x8b8b8b8b 填充
// seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251,
//          2341178251, 2341178251, 2341178251, 2341178251, 2341178251 }
//
// 步骤 2 :
// n = 10, s = 5, t = 3, p = 3, q = 6, m = 10
//
// 首次迭代, 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 } 
//
// 步骤 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 n : seeds)
        std::cout << n << '\n';
}

输出:

4204997637
4246533866
1856049002
1129615051
690460811
1075771511
46783058
3904109078
1534123438
1495905678