Mersenne Twister算法C#实现
mersennetwister梅森旋转算法

mersennetwister梅森旋转算法梅森旋转算法(Mersenne Twister)是一种用于生成伪随机数的算法,它由1997年由松本真(Makoto Matsumoto)和西村雅史(Takuji Nishimura)发明。
该算法以其良好的随机性和高速度而广受欢迎,成为了很多编程语言中的标准伪随机数生成器。
梅森旋转算法的名称来自于梅森素数,因为该算法使用了一种名为梅森素数的特殊质数进行计算。
在计算机科学领域,梅森素数指的是一种形式为2- 1的素数,其中p也是一个素数。
梅森旋转算法使用了一个称为MT19937的梅森素数,因此得名为梅森旋转算法。
梅森旋转算法的主要优点是它能够生成高质量的伪随机数序列,并且具有很长的周期。
周期指的是在产生的随机数序列中,所有可能的数值都会在一定的时间内出现,并且不会重复。
对于一个长度为n的随机数序列,其周期的上限是2^n - 1。
梅森旋转算法的周期非常长,能够达到2^19937 - 1,这意味着在一般的应用中,几乎可以认为是无限周期。
梅森旋转算法的实现相对较为简单,使用起来非常方便。
在很多编程语言中,都内建了该算法的实现,只需要简单的调用相应的函数即可得到随机数。
并且,算法的性能也比较好,生成的随机数速度很快,适用于大部分的应用场景。
然而,梅森旋转算法也存在一些缺点。
首先,因为其算法是确定性的,即给定相同的种子(或者初始状态),生成的随机数序列总是相同的。
这在某些场景下可能不够安全,因为攻击者可以通过分析已知的随机数序列来推测种子,从而破坏系统的安全性。
其次,梅森旋转算法虽然有很长的周期,但在某些特殊情况下仍然可能出现周期性的重复。
比如,如果种子的选择不够随机,或者使用了相同的种子,那么生成的随机数序列可能表现出明显的规律性,这就降低了算法的随机性。
另外,由于梅森旋转算法是一个线性递归算法,其内部使用了一系列的线性操作来产生随机数,这使得在某些统计测试中可能会出现一些问题,导致生成的随机数序列在统计上并不符合随机性的要求。
计算机仿真期末大作业Mersenne Twister随机数发生器及随机性测试

Mersenne Twister随机数发生器及随机性测试一、实验目的用MATLAB实现Mersenne Twister随机数发生器,并对其随机性进行测试。
二、实验原理伪随机数的产生,首先是选取种子,然后是在此种子基础上根据具体的生成算法计算得到一个伪随机数,然后利用此伪随机数再根据生成算法递归计算出下二个伪随机数,直到将所有不重复出现的伪随机数全部计算出来。
这个伪随机数序列就是以后要用到的伪随机数序列。
上面的计算过程可以一次性计算完毕,也可以使用一次递归计算一次,每次生成的伪随机数就是这个伪随机数序列中的一个,不过不管怎么样,只要确定了种子,确定了生成算法,这个序列就是确定的了。
所谓种子,就是一个对伪随机数计算的初始值。
Mersenne Twister算法是一种随机数产生方法,它是移位寄存器法的变种。
该算法的原理:Mersenne Twister算法是利用线性反馈移位寄存器(LFSR)产生随机数的,LFSR的反馈函数是寄存器中某些位的简单异或,这些位也称之为抽头序列。
一个n位的LFSR能够在重复之前产生2^n-1位长的伪随机序列。
只有具有一定抽头序列的LFSR才能通过所有2^n-1个内部状态,产生2^n - 1位长的伪随机序列,这个输出的序列就称之为m序列。
为了使LFSR成为最大周期的LFSR,由抽头序列加上常数1形成的多项式必须是本原多项式。
一个n阶本原多项式是不可约多项式,它能整除x^(2*n-1)+1而不能整除x^d+1,其中d能整除2^n-1。
例如(32,7,5,3,2,1,0)是指本原多项式x^32+x^7+x^5+x^3+x^2+x+1,把它转化为最大周期LFSR就是在LFSR小邓第32,7,5,2,1位抽头。
利用上述两种方法产生周期为m的伪随机序列后,只需要将产生的伪随机序列除以序列的周期,就可以得到(0,1)上均匀分布的伪随机序列了。
伪代码如下:// 建立624位随机序列数组int[0..623] MTint index = 0//初始化随机序列数组function initializeGenerator(int seed) {MT[0] := seedfor i from 1 to 623 {MT[i] := last 32 bits of(1812433253 * (MT[i-1] xor(right shift by 30 bits(MT[i-1]))) + i) // 0x6c078965}}//根据index的值提取数组中的某个数来生成随机数// 每624个数调用一次generateNumbers() 函数function extractNumber() {if index == 0 {generateNumbers()}int y := MT[index]y := y xor (right shift by 11 bits(y))y := y xor(left shift by 7 bits(y) and (2636928640)) // 0x9d2c5680 y := y xor(left shift by 15 bits(y) and(4022730752)) // 0xefc60000 y := y xor (right shift by 18 bits(y))index := (index + 1) mod 624return y}//产生随机数function generateNumbers() {for i from 0 to 623 {int y := 32nd bit of(MT[i]) + last 31 bits of(MT[(i+1) mod624]) MT[i] := MT[(i + 397) mod 624] xor (right shift by 1 bit(y)) if (y mod 2) != 0 { // y is oddMT[i] := MT[i] xor (2567483615) // 0x9908b0df}}}三、程序结构说明函数的伪代码已经在实验原理中给出。
随机数生成公式

随机数生成公式随机数生成公式是一种计算机程序中常用的技术,可以生成随机的数字,用于模拟和实验等场景中。
本文将介绍几种常见的随机数生成公式及其应用场景。
一、线性同余法(Linear Congruential Method)线性同余法是一种简单而又高效的随机数生成方法,其公式为:Xn+1 = (aXn + c) mod m其中Xn为当前随机数,a、c、m为常数,mod为模运算符。
该公式的原理是通过不断迭代计算,每次得到一个新的随机数。
该方法的优点是计算速度快,缺点是会产生周期性重复的随机数序列。
该方法常用于模拟和实验场景中。
二、梅森旋转算法(Mersenne Twister)梅森旋转算法是一种广泛应用的随机数生成方法,其公式为:Xn+1 = Xn⊕(Xn >> u)其中Xn为当前随机数,⊕为异或运算符,>>为右移运算符,u为常数。
该公式的原理是通过对当前随机数进行位运算,得到一个新的随机数。
该方法的优点是生成的随机数序列较为均匀,缺点是计算速度较慢。
该方法常用于加密和安全场景中。
三、高斯分布随机数生成公式(Gaussian Distribution)高斯分布随机数生成公式是一种生成符合正态分布(高斯分布)的随机数的方法,其公式为:X = μ + σ * Z其中μ为均值,σ为标准差,Z为符合标准正态分布的随机数。
该公式的原理是通过对标准正态分布进行线性变换,得到符合正态分布的随机数。
该方法的优点是生成的随机数符合实际分布规律,缺点是计算量较大。
该方法常用于金融和统计场景中。
四、指数分布随机数生成公式(Exponential Distribution)指数分布随机数生成公式是一种生成符合指数分布的随机数的方法,其公式为:X = -ln(U) / λ其中U为符合均匀分布的随机数,ln为自然对数函数,λ为指数分布的参数。
该公式的原理是通过对均匀分布进行变换,得到符合指数分布的随机数。
梅森旋转算法c++

梅森旋转的C++算法示例梅森旋转算法(Mersenne Twister Algorithm)是一种广泛用于生成伪随机数的算法。
下面是一个使用C++实现梅森旋转算法的示例:```cpp#include <iostream>#include <random>int main() {// 使用梅森旋转算法生成随机数引擎std::mt19937 engine(std::random_device{}());// 生成随机整数std::uniform_int_distribution<int> dist(1, 100);int randomInt = dist(engine);std::cout << "随机整数: " << randomInt << std::endl;// 生成随机浮点数std::uniform_real_distribution<double> dist2(0.0, 1.0);double randomDouble = dist2(engine);std::cout << "随机浮点数: " << randomDouble << std::endl;return 0;}```在上面的示例中,我们使用`std::mt19937`类作为梅森旋转算法的随机数引擎。
通过提供一个随机设备(`std::random_device`)的种子,我们创建了一个初始化的引擎。
然后,我们使用`std::uniform_int_distribution`和`std::uniform_real_distribution`类来定义整数和浮点数的分布范围。
通过将引擎作为参数传递给这些分布对象,我们可以生成不同范围内的随机数。
请注意,每次运行程序时,生成的随机数会有所不同,因为我们使用了随机设备作为种子来初始化引擎。
mersenne twister 梅森旋转算法

mersenne twister 梅森旋转算法The Mersenne Twister algorithm is a widely used pseudo-random number generator that is known for its speed and high-quality random numbers. 梅森旋转算法是一种广泛使用的伪随机数生成器,以其速度和高质量的随机数而闻名。
It was developed in 1997 by Makoto Matsumoto and Takuji Nishimura and is based on a matrix linear recurrence over a finite binary field. 它是由松本真和西村拓士于1997年开发的,基于有限二进制域上的矩阵线性递推。
The algorithm is designed to have a very long period of 2^19937 - 1, meaning that it can generate a huge number of unique random numbers before repeating. 该算法的设计周期非常长,为2^19937 - 1,意味着它可以在重复之前生成大量不重复的随机数。
One of the key features of the Mersenne Twister algorithm is its high-quality random number generation, which is achieved through a large state space and a long period. 梅森旋转算法的一个关键特点是通过大状态空间和长周期实现高质量的随机数生成。
This makes it ideal for various applications such as simulations, numerical analysis, and cryptography. 这使得它非常适合用于各种应用,如仿真、数值分析和密码学。
基于检验的随机数在线检测方法的实现

基于检验的随机数在线检测方法的实现一、概述随着信息化时代的快速发展,随机数在信息安全、通信、密码学等多个领域扮演着至关重要的角色。
它们被广泛应用于生成密钥、加密解密、身份认证等关键过程,对于保障信息安全具有不可或缺的作用。
随机数的质量直接影响到这些应用的安全性和可靠性,对随机数进行在线检测以确保其质量和随机性成为一项重要任务。
传统的随机数检测方法往往依赖于离线分析,这种方法虽然能够提供较为准确的检测结果,但无法满足实时性和在线性的要求。
开发一种基于检验的随机数在线检测方法具有重要的实际意义。
该方法能够实时地对随机数进行监测和分析,及时发现并处理可能存在的问题,从而确保随机数的质量和随机性。
本文提出了一种基于检验的随机数在线检测方法的实现方案。
该方法首先采集大量的随机数样本,然后利用统计学原理对样本进行卡方检验,以评估随机数的质量和随机性。
针对128bit、256bit和512bit等不同长度的随机数,我们通过推导和优化卡方检验公式,使其更易于硬件实现,从而提高了在线检测的速度和效率。
1. 随机数在各个领域的应用及其重要性随机数在现代社会的各个领域中均扮演着不可或缺的角色,其重要性和应用价值日益凸显。
无论是在科学研究、工程技术、金融投资,还是在信息安全、网络通信、游戏娱乐等领域,随机数都发挥着至关重要的作用。
在科学研究领域,随机数被广泛用于模拟实验、统计分析以及模型构建等方面。
通过生成大量的随机数样本,科学家们能够模拟出各种复杂的自然现象和社会过程,从而揭示其中的规律和机制。
随机数在统计分析中也扮演着重要角色,能够帮助研究者们更准确地评估数据的分布特征、检验假设的合理性以及预测未来的趋势。
在工程技术领域,随机数同样具有广泛的应用。
在通信系统中,随机数可以用于生成加密密钥和随机数序列,保障信息传输的安全性和可靠性。
在图像处理领域,随机数可以用于生成噪声、纹理等效果,增强图像的视觉体验。
在工业自动化、控制系统等领域,随机数也发挥着重要作用,能够提高系统的稳定性和性能。
Mersenne Twister算法C#实现

using System;namespace RandomTest{public class MersenneTwister : Random{/// <summary>/// Creates a new pseudo-random number generator with a given seed./// </summary>/// <param name="seed">A value to use as a seed.</param>public MersenneTwister(Int32 seed){init((UInt32)seed);}/// <summary>/// Creates a new pseudo-random number generator with a default seed./// </summary>/// <remarks>/// <c>new <see cref="System.Random"/>().<see cref="Random.Next()"/></c>/// is used for the seed./// </remarks>public MersenneTwister(): this(new Random().Next()) /* a default initial seed is used */ { }/// <summary>/// Creates a pseudo-random number generator initialized with the given array./// </summary>/// <param name="initKey">The array for initializing keys.</param>public MersenneTwister(Int32[] initKey){if (initKey == null){throw new ArgumentNullException("initKey");}UInt32[] initArray = new UInt32[initKey.Length];for (int i = 0; i < initKey.Length; ++i){initArray[i] = (UInt32)initKey[i];}init(initArray);}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/>./// </summary>/// <returns>A pseudo-random <see cref="UInt32"/> value.</returns>public virtual UInt32 NextUInt32(){return GenerateUInt32();}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/>/// up to <paramref name="maxValue"/>./// </summary>/// <param name="maxValue">/// The maximum value of the pseudo-random number to create./// </param>/// <returns>/// A pseudo-random <see cref="UInt32"/> value which is at most <paramref name="maxValue"/>./// </returns>public virtual UInt32 NextUInt32(UInt32 maxValue){return (UInt32)(GenerateUInt32() / ((Double)UInt32.MaxValue / maxValue));}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/> at least/// <paramref name="minValue"/> and up to <paramref name="maxValue"/>./// </summary>/// <param name="minValue">The minimum value of the pseudo-random number to create.</param>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>/// A pseudo-random <see cref="UInt32"/> value which is at least/// <paramref name="minValue"/> and at most <paramref name="maxValue"/>./// </returns>/// <exception cref="ArgumentOutOfRangeException">/// If <c><paramref name="minValue"/> >= <paramref name="maxValue"/></c>./// </exception>public virtual UInt32 NextUInt32(UInt32 minValue, UInt32 maxValue) /* throws ArgumentOutOfRangeException */{if (minValue >= maxValue){throw new ArgumentOutOfRangeException();}return (UInt32)(GenerateUInt32() / ((Double)UInt32.MaxValue / (maxValue - minValue)) + minValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/>./// </summary>/// <returns>A pseudo-random <see cref="Int32"/> value.</returns>public override Int32 Next(){return Next(Int32.MaxValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/> up to <paramref name="maxValue"/>./// </summary>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>/// A pseudo-random <see cref="Int32"/> value which is at most <paramref name="maxValue"/>./// </returns>/// <exception cref="ArgumentOutOfRangeException">/// When <paramref name="maxValue"/> < 0./// </exception>public override Int32 Next(Int32 maxValue){if (maxValue <= 1){if (maxValue < 0){throw new ArgumentOutOfRangeException();}return 0;}return (Int32)(NextDouble() * maxValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/>/// at least <paramref name="minValue"/>/// and up to <paramref name="maxValue"/>./// </summary>/// <param name="minValue">The minimum value of the pseudo-random number to create.</param>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>A pseudo-random Int32 value which is at least <paramref name="minValue"/> and at/// most <paramref name="maxValue"/>.</returns>/// <exception cref="ArgumentOutOfRangeException">/// If <c><paramref name="minValue"/> >= <paramref name="maxValue"/></c>./// </exception>public override Int32 Next(Int32 minValue, Int32 maxValue){if (maxValue <= minValue){throw new ArgumentOutOfRangeException();}if (maxValue == minValue){return minValue;}return Next(maxValue - minValue) + minValue;}/// <summary>/// Fills a buffer with pseudo-random bytes./// </summary>/// <param name="buffer">The buffer to fill.</param>/// <exception cref="ArgumentNullException">/// If <c><paramref name="buffer"/> == <see langword="null"/></c>./// </exception>public override void NextBytes(Byte[] buffer){// [codekaizen: corrected this to check null before checking length.]if (buffer == null){throw new ArgumentNullException();}Int32 bufLen = buffer.Length;for (Int32 idx = 0; idx < bufLen; ++idx){buffer[idx] = (Byte)Next(256);}}/// <summary>/// Returns the next pseudo-random <see cref="Double"/> value./// </summary>/// <returns>A pseudo-random double floating point value.</returns>/// <remarks>/// <para>/// There are two common ways to create a double floating point using MT19937:/// using <see cref="GenerateUInt32"/> and dividing by 0xFFFFFFFF + 1,/// or else generating two double words and shifting the first by 26 bits and/// adding the second./// </para>/// <para>/// In a newer measurement of the randomness of MT19937 published in the/// journal "Monte Carlo Methods and Applications, Vol. 12, No. 5-6, pp. 385 ?393 (2006)"/// entitled "A Repetition Test for Pseudo-Random Number Generators",/// it was found that the 32-bit version of generating a double fails at the 95%/// confidence level when measuring for expected repetitions of a particular/// number in a sequence of numbers generated by the algorithm./// </para>/// <para>/// Due to this, the 53-bit method is implemented here and the 32-bit method/// of generating a double is not. If, for some reason,/// the 32-bit method is needed, it can be generated by the following:/// <code>/// (Double)NextUInt32() / ((UInt64)UInt32.MaxValue + 1);/// </code>/// </para>/// </remarks>public override Double NextDouble(){return compute53BitRandom(0, InverseOnePlus53BitsOf1s);}/// <summary>/// Returns a pseudo-random number greater than or equal to zero, and/// either strictly less than one, or less than or equal to one,/// depending on the value of the given parameter./// </summary>/// <param name="includeOne">/// If <see langword="true"/>, the pseudo-random number returned will be/// less than or equal to one; otherwise, the pseudo-random number returned will/// be strictly less than one./// </param>/// <returns>/// If <paramref name="includeOne"/> is <see langword="true"/>,/// this method returns a double-precision pseudo-random number greater than/// or equal to zero, and less than or equal to one./// If <paramref name="includeOne"/> is <see langword="false"/>, this method/// returns a double-precision pseudo-random number greater than or equal to zero and/// strictly less than one./// </returns>public Double NextDouble(Boolean includeOne){return includeOne ? compute53BitRandom(0, Inverse53BitsOf1s) : NextDouble();}/// <summary>/// Returns a pseudo-random number greater than 0.0 and less than 1.0./// </summary>/// <returns>A pseudo-random number greater than 0.0 and less than 1.0.</returns>public Double NextDoublePositive(){return compute53BitRandom(0.5, Inverse53BitsOf1s);}/// <summary>/// Returns a pseudo-random number between 0.0 and 1.0./// </summary>/// <returns>/// A single-precision floating point number greater than or equal to 0.0,/// and less than 1.0./// </returns>public Single NextSingle(){return (Single)NextDouble();}/// <summary>/// Returns a pseudo-random number greater than or equal to zero, and either strictly/// less than one, or less than or equal to one, depending on the value of the/// given boolean parameter./// </summary>/// <param name="includeOne">/// If <see langword="true"/>, the pseudo-random number returned will be/// less than or equal to one; otherwise, the pseudo-random number returned will/// be strictly less than one./// </param>/// <returns>/// If <paramref name="includeOne"/> is <see langword="true"/>, this method returns a/// single-precision pseudo-random number greater than or equal to zero, and less/// than or equal to one. If <paramref name="includeOne"/> is <see langword="false"/>,/// this method returns a single-precision pseudo-random number greater than or equal to zero and/// strictly less than one./// </returns>public Single NextSingle(Boolean includeOne){return (Single)NextDouble(includeOne);}/// <summary>/// Returns a pseudo-random number greater than 0.0 and less than 1.0./// </summary>/// <returns>A pseudo-random number greater than 0.0 and less than 1.0.</returns>public Single NextSinglePositive(){return (Single)NextDoublePositive();}/// <summary>/// Generates a new pseudo-random <see cref="UInt32"/>./// </summary>/// <returns>A pseudo-random <see cref="UInt32"/>.</returns>protected UInt32 GenerateUInt32(){UInt32 y;/* _mag01[x] = x * MatrixA for x=0,1 */if (_mti >= N) /* generate N words at one time */{Int16 kk = 0;for (; kk < N - M; ++kk){y = (_mt[kk] & UpperMask) | (_mt[kk + 1] & LowerMask);_mt[kk] = _mt[kk + M] ^ (y >> 1) ^ _mag01[y & 0x1];}for (; kk < N - 1; ++kk){y = (_mt[kk] & UpperMask) | (_mt[kk + 1] & LowerMask);_mt[kk] = _mt[kk + (M - N)] ^ (y >> 1) ^ _mag01[y & 0x1];}y = (_mt[N - 1] & UpperMask) | (_mt[0] & LowerMask);_mt[N - 1] = _mt[M - 1] ^ (y >> 1) ^ _mag01[y & 0x1];_mti = 0;}y = _mt[_mti++];y ^= temperingShiftU(y);y ^= temperingShiftS(y) & TemperingMaskB;y ^= temperingShiftT(y) & TemperingMaskC;y ^= temperingShiftL(y);return y;}/* Period parameters */private const Int32 N = 624;private const Int32 M = 397;private const UInt32 MatrixA = 0x9908b0df; /* constant vector a */private const UInt32 UpperMask = 0x80000000; /* most significant w-r bits */ private const UInt32 LowerMask = 0x7fffffff; /* least significant r bits *//* Tempering parameters */private const UInt32 TemperingMaskB = 0x9d2c5680;private const UInt32 TemperingMaskC = 0xefc60000;private static UInt32 temperingShiftU(UInt32 y){return (y >> 11);}private static UInt32 temperingShiftS(UInt32 y){return (y << 7);}private static UInt32 temperingShiftT(UInt32 y){return (y << 15);}private static UInt32 temperingShiftL(UInt32 y){return (y >> 18);}private readonly UInt32[] _mt = new UInt32[N]; /* the array for the state vector */private Int16 _mti;private static readonly UInt32[] _mag01 = { 0x0, MatrixA };private void init(UInt32 seed){_mt[0] = seed & 0xffffffffU;for (_mti = 1; _mti < N; _mti++){_mt[_mti] = (uint)(1812433253U * (_mt[_mti - 1] ^ (_mt[_mti - 1] >> 30)) + _mti);// See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.// In the previous versions, MSBs of the seed affect// only MSBs of the array _mt[].// 2002/01/09 modified by Makoto Matsumoto_mt[_mti] &= 0xffffffffU;// for >32 bit machines}}private void init(UInt32[] key){Int32 i, j, k;init(19650218U);Int32 keyLength = key.Length;i = 1; j = 0;k = (N > keyLength ? N : keyLength);for (; k > 0; k--){_mt[i] = (uint)((_mt[i] ^ ((_mt[i - 1] ^ (_mt[i - 1] >> 30)) * 1664525U)) + key[j] + j); /* non linear */_mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machinesi++; j++;if (i >= N) { _mt[0] = _mt[N - 1]; i = 1; }if (j >= keyLength) j = 0;}for (k = N - 1; k > 0; k--){_mt[i] = (uint)((_mt[i] ^ ((_mt[i - 1] ^ (_mt[i - 1] >> 30)) * 1566083941U)) - i); /* non linear */_mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machinesi++;if (i < N){continue;}_mt[0] = _mt[N - 1]; i = 1;}_mt[0] = 0x80000000U; // MSB is 1; assuring non-zero initial array}// 9007199254740991.0 is the maximum double value which the 53 significand// can hold when the exponent is 0.private const Double FiftyThreeBitsOf1s = 9007199254740991.0;// Multiply by inverse to (vainly?) try to avoid a division.private const Double Inverse53BitsOf1s = 1.0 / FiftyThreeBitsOf1s;private const Double OnePlus53BitsOf1s = FiftyThreeBitsOf1s + 1;private const Double InverseOnePlus53BitsOf1s = 1.0 / OnePlus53BitsOf1s;private Double compute53BitRandom(Double translate, Double scale){// get 27 pseudo-random bitsUInt64 a = (UInt64)GenerateUInt32() >> 5;// get 26 pseudo-random bitsUInt64 b = (UInt64)GenerateUInt32() >> 6;// shift the 27 pseudo-random bits (a) over by 26 bits (* 67108864.0) and// add another pseudo-random 26 bits (+ b).return ((a * 67108864.0 + b) + translate) * scale;// What about the following instead of the above? Is the multiply better?// Why? (Is it the FMUL instruction? Does this count in .Net? Will the JITter notice?)//return BitConverter.Int64BitsToDouble((a << 26) + b));}}}。
fortran梅森旋转算法

fortran梅森旋转算法
梅森旋转算法(Mersenne Twister)是一种高效且广泛使用的伪随机数生成算法,由松本真和西村拓士在1997年开发。
该算法基于有限二进制字段上的矩阵线性递归,可以快速生成高质量的伪随机数,修正了古典随机数生成算法的许多缺陷。
在Fortran中实现梅森旋转算法,可以利用该算法的特性来生成高质量的随机数序列。
梅森旋转算法的核心是一个线性反馈移位寄存器(LFSR),它通过一系列位操作和加法运算来生成随机数。
在Fortran中,可以使用位运算符和整数数据类型来实现这个算法。
首先,定义一个足够大的整数变量作为状态寄存器,初始化为一个特定的种子值。
然后,通过一系列的位操作和加法运算来更新状态寄存器的值,生成新的随机数。
梅森旋转算法的一个重要特点是其周期长,这保证了生成的随机数序列具有很好的统计性质。
在Fortran实现中,可以通过循环来不断生成新的随机数,直到达到所需的随机数数量。
此外,梅森旋转算法还具有很好的并行性,可以在多核处理器上实现高效的并行随机数生成。
这对于需要大规模随机数生成的应用程序来说非常有用。
总的来说,Fortran实现梅森旋转算法需要深入理解算法的原理和特性,并充分利用Fortran的位运算符和整数数据类型来实现高效的随机数生成。
这种算法在实际应用中具有广泛的应用前景,可以用于模拟、统计分析和密码学等领域。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
using System;namespace RandomTest{public class MersenneTwister : Random{/// <summary>/// Creates a new pseudo-random number generator with a given seed./// </summary>/// <param name="seed">A value to use as a seed.</param>public MersenneTwister(Int32 seed){init((UInt32)seed);}/// <summary>/// Creates a new pseudo-random number generator with a default seed./// </summary>/// <remarks>/// <c>new <see cref="System.Random"/>().<see cref="Random.Next()"/></c>/// is used for the seed./// </remarks>public MersenneTwister(): this(new Random().Next()) /* a default initial seed is used */ { }/// <summary>/// Creates a pseudo-random number generator initialized with the given array./// </summary>/// <param name="initKey">The array for initializing keys.</param>public MersenneTwister(Int32[] initKey){if (initKey == null){throw new ArgumentNullException("initKey");}UInt32[] initArray = new UInt32[initKey.Length];for (int i = 0; i < initKey.Length; ++i){initArray[i] = (UInt32)initKey[i];}init(initArray);}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/>./// </summary>/// <returns>A pseudo-random <see cref="UInt32"/> value.</returns>public virtual UInt32 NextUInt32(){return GenerateUInt32();}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/>/// up to <paramref name="maxValue"/>./// </summary>/// <param name="maxValue">/// The maximum value of the pseudo-random number to create./// </param>/// <returns>/// A pseudo-random <see cref="UInt32"/> value which is at most <paramref name="maxValue"/>./// </returns>public virtual UInt32 NextUInt32(UInt32 maxValue){return (UInt32)(GenerateUInt32() / ((Double)UInt32.MaxValue / maxValue));}/// <summary>/// Returns the next pseudo-random <see cref="UInt32"/> at least/// <paramref name="minValue"/> and up to <paramref name="maxValue"/>./// </summary>/// <param name="minValue">The minimum value of the pseudo-random number to create.</param>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>/// A pseudo-random <see cref="UInt32"/> value which is at least/// <paramref name="minValue"/> and at most <paramref name="maxValue"/>./// </returns>/// <exception cref="ArgumentOutOfRangeException">/// If <c><paramref name="minValue"/> >= <paramref name="maxValue"/></c>./// </exception>public virtual UInt32 NextUInt32(UInt32 minValue, UInt32 maxValue) /* throws ArgumentOutOfRangeException */{if (minValue >= maxValue){throw new ArgumentOutOfRangeException();}return (UInt32)(GenerateUInt32() / ((Double)UInt32.MaxValue / (maxValue - minValue)) + minValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/>./// </summary>/// <returns>A pseudo-random <see cref="Int32"/> value.</returns>public override Int32 Next(){return Next(Int32.MaxValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/> up to <paramref name="maxValue"/>./// </summary>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>/// A pseudo-random <see cref="Int32"/> value which is at most <paramref name="maxValue"/>./// </returns>/// <exception cref="ArgumentOutOfRangeException">/// When <paramref name="maxValue"/> < 0./// </exception>public override Int32 Next(Int32 maxValue){if (maxValue <= 1){if (maxValue < 0){throw new ArgumentOutOfRangeException();}return 0;}return (Int32)(NextDouble() * maxValue);}/// <summary>/// Returns the next pseudo-random <see cref="Int32"/>/// at least <paramref name="minValue"/>/// and up to <paramref name="maxValue"/>./// </summary>/// <param name="minValue">The minimum value of the pseudo-random number to create.</param>/// <param name="maxValue">The maximum value of the pseudo-random number to create.</param>/// <returns>A pseudo-random Int32 value which is at least <paramref name="minValue"/> and at/// most <paramref name="maxValue"/>.</returns>/// <exception cref="ArgumentOutOfRangeException">/// If <c><paramref name="minValue"/> >= <paramref name="maxValue"/></c>./// </exception>public override Int32 Next(Int32 minValue, Int32 maxValue){if (maxValue <= minValue){throw new ArgumentOutOfRangeException();}if (maxValue == minValue){return minValue;}return Next(maxValue - minValue) + minValue;}/// <summary>/// Fills a buffer with pseudo-random bytes./// </summary>/// <param name="buffer">The buffer to fill.</param>/// <exception cref="ArgumentNullException">/// If <c><paramref name="buffer"/> == <see langword="null"/></c>./// </exception>public override void NextBytes(Byte[] buffer){// [codekaizen: corrected this to check null before checking length.]if (buffer == null){throw new ArgumentNullException();}Int32 bufLen = buffer.Length;for (Int32 idx = 0; idx < bufLen; ++idx){buffer[idx] = (Byte)Next(256);}}/// <summary>/// Returns the next pseudo-random <see cref="Double"/> value./// </summary>/// <returns>A pseudo-random double floating point value.</returns>/// <remarks>/// <para>/// There are two common ways to create a double floating point using MT19937:/// using <see cref="GenerateUInt32"/> and dividing by 0xFFFFFFFF + 1,/// or else generating two double words and shifting the first by 26 bits and/// adding the second./// </para>/// <para>/// In a newer measurement of the randomness of MT19937 published in the/// journal "Monte Carlo Methods and Applications, Vol. 12, No. 5-6, pp. 385 ?393 (2006)"/// entitled "A Repetition Test for Pseudo-Random Number Generators",/// it was found that the 32-bit version of generating a double fails at the 95%/// confidence level when measuring for expected repetitions of a particular/// number in a sequence of numbers generated by the algorithm./// </para>/// <para>/// Due to this, the 53-bit method is implemented here and the 32-bit method/// of generating a double is not. If, for some reason,/// the 32-bit method is needed, it can be generated by the following:/// <code>/// (Double)NextUInt32() / ((UInt64)UInt32.MaxValue + 1);/// </code>/// </para>/// </remarks>public override Double NextDouble(){return compute53BitRandom(0, InverseOnePlus53BitsOf1s);}/// <summary>/// Returns a pseudo-random number greater than or equal to zero, and/// either strictly less than one, or less than or equal to one,/// depending on the value of the given parameter./// </summary>/// <param name="includeOne">/// If <see langword="true"/>, the pseudo-random number returned will be/// less than or equal to one; otherwise, the pseudo-random number returned will/// be strictly less than one./// </param>/// <returns>/// If <paramref name="includeOne"/> is <see langword="true"/>,/// this method returns a double-precision pseudo-random number greater than/// or equal to zero, and less than or equal to one./// If <paramref name="includeOne"/> is <see langword="false"/>, this method/// returns a double-precision pseudo-random number greater than or equal to zero and/// strictly less than one./// </returns>public Double NextDouble(Boolean includeOne){return includeOne ? compute53BitRandom(0, Inverse53BitsOf1s) : NextDouble();}/// <summary>/// Returns a pseudo-random number greater than 0.0 and less than 1.0./// </summary>/// <returns>A pseudo-random number greater than 0.0 and less than 1.0.</returns>public Double NextDoublePositive(){return compute53BitRandom(0.5, Inverse53BitsOf1s);}/// <summary>/// Returns a pseudo-random number between 0.0 and 1.0./// </summary>/// <returns>/// A single-precision floating point number greater than or equal to 0.0,/// and less than 1.0./// </returns>public Single NextSingle(){return (Single)NextDouble();}/// <summary>/// Returns a pseudo-random number greater than or equal to zero, and either strictly/// less than one, or less than or equal to one, depending on the value of the/// given boolean parameter./// </summary>/// <param name="includeOne">/// If <see langword="true"/>, the pseudo-random number returned will be/// less than or equal to one; otherwise, the pseudo-random number returned will/// be strictly less than one./// </param>/// <returns>/// If <paramref name="includeOne"/> is <see langword="true"/>, this method returns a/// single-precision pseudo-random number greater than or equal to zero, and less/// than or equal to one. If <paramref name="includeOne"/> is <see langword="false"/>,/// this method returns a single-precision pseudo-random number greater than or equal to zero and/// strictly less than one./// </returns>public Single NextSingle(Boolean includeOne){return (Single)NextDouble(includeOne);}/// <summary>/// Returns a pseudo-random number greater than 0.0 and less than 1.0./// </summary>/// <returns>A pseudo-random number greater than 0.0 and less than 1.0.</returns>public Single NextSinglePositive(){return (Single)NextDoublePositive();}/// <summary>/// Generates a new pseudo-random <see cref="UInt32"/>./// </summary>/// <returns>A pseudo-random <see cref="UInt32"/>.</returns>protected UInt32 GenerateUInt32(){UInt32 y;/* _mag01[x] = x * MatrixA for x=0,1 */if (_mti >= N) /* generate N words at one time */{Int16 kk = 0;for (; kk < N - M; ++kk){y = (_mt[kk] & UpperMask) | (_mt[kk + 1] & LowerMask);_mt[kk] = _mt[kk + M] ^ (y >> 1) ^ _mag01[y & 0x1];}for (; kk < N - 1; ++kk){y = (_mt[kk] & UpperMask) | (_mt[kk + 1] & LowerMask);_mt[kk] = _mt[kk + (M - N)] ^ (y >> 1) ^ _mag01[y & 0x1];}y = (_mt[N - 1] & UpperMask) | (_mt[0] & LowerMask);_mt[N - 1] = _mt[M - 1] ^ (y >> 1) ^ _mag01[y & 0x1];_mti = 0;}y = _mt[_mti++];y ^= temperingShiftU(y);y ^= temperingShiftS(y) & TemperingMaskB;y ^= temperingShiftT(y) & TemperingMaskC;y ^= temperingShiftL(y);return y;}/* Period parameters */private const Int32 N = 624;private const Int32 M = 397;private const UInt32 MatrixA = 0x9908b0df; /* constant vector a */private const UInt32 UpperMask = 0x80000000; /* most significant w-r bits */ private const UInt32 LowerMask = 0x7fffffff; /* least significant r bits *//* Tempering parameters */private const UInt32 TemperingMaskB = 0x9d2c5680;private const UInt32 TemperingMaskC = 0xefc60000;private static UInt32 temperingShiftU(UInt32 y){return (y >> 11);}private static UInt32 temperingShiftS(UInt32 y){return (y << 7);}private static UInt32 temperingShiftT(UInt32 y){return (y << 15);}private static UInt32 temperingShiftL(UInt32 y){return (y >> 18);}private readonly UInt32[] _mt = new UInt32[N]; /* the array for the state vector */private Int16 _mti;private static readonly UInt32[] _mag01 = { 0x0, MatrixA };private void init(UInt32 seed){_mt[0] = seed & 0xffffffffU;for (_mti = 1; _mti < N; _mti++){_mt[_mti] = (uint)(1812433253U * (_mt[_mti - 1] ^ (_mt[_mti - 1] >> 30)) + _mti);// See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.// In the previous versions, MSBs of the seed affect// only MSBs of the array _mt[].// 2002/01/09 modified by Makoto Matsumoto_mt[_mti] &= 0xffffffffU;// for >32 bit machines}}private void init(UInt32[] key){Int32 i, j, k;init(19650218U);Int32 keyLength = key.Length;i = 1; j = 0;k = (N > keyLength ? N : keyLength);for (; k > 0; k--){_mt[i] = (uint)((_mt[i] ^ ((_mt[i - 1] ^ (_mt[i - 1] >> 30)) * 1664525U)) + key[j] + j); /* non linear */_mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machinesi++; j++;if (i >= N) { _mt[0] = _mt[N - 1]; i = 1; }if (j >= keyLength) j = 0;}for (k = N - 1; k > 0; k--){_mt[i] = (uint)((_mt[i] ^ ((_mt[i - 1] ^ (_mt[i - 1] >> 30)) * 1566083941U)) - i); /* non linear */_mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machinesi++;if (i < N){continue;}_mt[0] = _mt[N - 1]; i = 1;}_mt[0] = 0x80000000U; // MSB is 1; assuring non-zero initial array}// 9007199254740991.0 is the maximum double value which the 53 significand// can hold when the exponent is 0.private const Double FiftyThreeBitsOf1s = 9007199254740991.0;// Multiply by inverse to (vainly?) try to avoid a division.private const Double Inverse53BitsOf1s = 1.0 / FiftyThreeBitsOf1s;private const Double OnePlus53BitsOf1s = FiftyThreeBitsOf1s + 1;private const Double InverseOnePlus53BitsOf1s = 1.0 / OnePlus53BitsOf1s;private Double compute53BitRandom(Double translate, Double scale){// get 27 pseudo-random bitsUInt64 a = (UInt64)GenerateUInt32() >> 5;// get 26 pseudo-random bitsUInt64 b = (UInt64)GenerateUInt32() >> 6;// shift the 27 pseudo-random bits (a) over by 26 bits (* 67108864.0) and// add another pseudo-random 26 bits (+ b).return ((a * 67108864.0 + b) + translate) * scale;// What about the following instead of the above? Is the multiply better?// Why? (Is it the FMUL instruction? Does this count in .Net? Will the JITter notice?)//return BitConverter.Int64BitsToDouble((a << 26) + b));}}}。