C# Random(staticSeed).Next()替代方案,永远不会改变实现,并保证在所有版本中保持一致

C# Random(staticSeed).Next()替代方案,永远不会改变实现,并保证在所有版本中保持一致,c#,.net,random,C#,.net,Random,我在找类似的东西,比如: new Random(staticSeed).Next() 但我确信,通过不同的.NET framework版本,实现将始终保持一致 我特别想要的是: …生成满足特定统计条件的数字序列 随机性要求 …引用System.Random类中的注释 在.NET中有类似的东西吗?还是我必须自己滚动 现在有什么特别推荐的算法吗 它不用于安全。在.NET中没有这样的东西。您可能应该从web复制RNG的代码。我建议使用异或移位算法。它有非常高的质量,是超级快速和易于实施(5行我

我在找类似的东西,比如:

new Random(staticSeed).Next() 
但我确信,通过不同的.NET framework版本,实现将始终保持一致

我特别想要的是:

…生成满足特定统计条件的数字序列 随机性要求

…引用
System.Random
类中的注释

  • 在.NET中有类似的东西吗?还是我必须自己滚动
  • 现在有什么特别推荐的算法吗

它不用于安全。

在.NET中没有这样的东西。您可能应该从web复制RNG的代码。我建议使用异或移位算法。它有非常高的质量,是超级快速和易于实施(5行我认为)


主观提示:应该是框架使用的算法。现有的算法似乎很差。

[这是usr答案的补充]

以下是XorShift RNG的C#实现,移植自:

公共密封类XorShiftRng:随机
{
公共XorShiftRng(乌龙种子1、乌龙种子2)
{
if(seed1==0&&seed2==0)
抛出新ArgumentException(“种子1和种子2不能都为零”);
s[0]=seed1;
s[1]=seed2;
}
公共XorShiftRng()
{
var bytes=Guid.NewGuid().ToByteArray();
s[0]=位转换器.ToUInt64(字节,0);
s[1]=位转换器.ToUInt64(字节,8);
}
公共乌龙-下图龙()
{
未经检查
{
ulong s0=s[p];
乌隆s1=s[p=(p+1)和15];
s1^=s1>11^(s0>>30);
返回s[p]*1181783497276652981;
}
}
公共长NextLong(长最大值)
{
返回(int)下一个长度(0,最大值);
}
公共长NextLong(长最小值,长最大值)
{
如果(最小值>最大值)
抛出新ArgumentOutOfRangeException(nameof(minValue),“minValue不能超过maxValue”);
如果(minValue==maxValue)
返回最小值;
返回(int)(NextUlong()/((double)ulong.MaxValue/(MaxValue-minValue))+minValue);
}
公共覆盖int Next()
{
返回(int)下一个长度(0,int.MaxValue+1L);
}
公共覆盖int-Next(int-maxValue)
{
返回(int)下一个长度(0,最大值+1L);
}
公共覆盖int-Next(int-minValue,int-maxValue)
{
返回(int)NextLong(minValue,maxValue);
}
公共覆盖无效下一个字节(字节[]缓冲区)
{
if(buffer==null)
抛出新ArgumentNullException(nameof(buffer));
剩余整数=缓冲区长度;
而(剩余>0)
{
var next=BitConverter.GetBytes(NextUlong());
int n=Math.Min(next.Length,剩余);
Array.Copy(next,0,buffer,buffer.Length-remaining,n);
剩余-=n;
}
}
public override double NextDouble()
{
返回NextUlong()/(ulong.MaxValue+1.0);
}
只读ulong[]s=新ulong[16];
INTP;
}
它有一个长周期2^1024− 1,并给出了非常好的随机数

有关更多详细信息,请参阅


[编辑]更新类以实现
类系统。Random

一种内置方法,用于获得种子随机序列,而无需滚动您自己的已知算法实现,即使用该类。将种子作为
密码
传递,使用一些固定或录制的
salt
,并将1传递给
迭代
,因为您不需要多次迭代的安全性


这将为您提供来自调用的无限字节数,每次调用都将返回相同的序列,用于相同的初始
密码
salt
,以及
ITTERTIONS
值,并且不会在.NET版本之间更改。

也许这会给您一些想法:实际上我不确定您要的是什么
new Random(staticSeed)。Next()
(当我将
staticSeed
理解为常量值时)将始终返回相同的数字,因为它是由该种子初始化的序列中的第一个伪随机数。嗨,Rene,我可能需要澄清我的问题。这正是我正在寻找的行为——一个随机的序列,我可以永远再生。想象一下游戏级别的随机生成器,你可以通过保存初始种子来保持整个状态。Mersenne Twister实际上是一个非常糟糕的算法。它的质量不是很好,速度慢,并且有大量的状态(1.7KB!)。我认为这是一种反模式。@usr它相对较慢,但绝对不是一种“反模式”。它的主要优势,如甲板洗牌的应用是它的周期非常长。它也常用于数值应用程序,如MATLAB(默认的RNG)。我知道它在任何地方都被使用,但如果维基百科可以信任的话,它就不应该被使用。XorShift+或XorShift*是通过所有流行随机性测试的简单变体(速度慢一倍)。在我看来,XorShift(+/*)在各个方面都更好,有时甚至更好。一般来说,我不喜欢基于数学技巧的RNG。线性同余是这些超级流行的垃圾生成器中的另一个。@usr好的,我看看是否可以相应地更新答案。答案很好,谢谢各位。你们想把XorShift的代码从我的答案复制到你们的答案中,这样我就可以删除我的答案了吗?@MatthewWatson我想这样可以。
public sealed class XorShiftRng: Random
{
    public XorShiftRng(ulong seed1, ulong seed2)
    {
        if (seed1 == 0 && seed2 == 0)
            throw new ArgumentException("seed1 and seed 2 cannot both be zero.");

        s[0] = seed1;
        s[1] = seed2;
    }

    public XorShiftRng()
    {
        var bytes = Guid.NewGuid().ToByteArray();

        s[0] = BitConverter.ToUInt64(bytes, 0);
        s[1] = BitConverter.ToUInt64(bytes, 8);
    }

    public ulong NextUlong()
    {
        unchecked
        {
            ulong s0 = s[p];
            ulong s1 = s[p = (p + 1) & 15];
            s1 ^= s1 << 31;
            s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30);
            return s[p]*1181783497276652981;
        }
    }

    public long NextLong(long maxValue)
    {
        return (int)NextLong(0, maxValue);
    }

    public long NextLong(long minValue, long maxValue)
    {
        if (minValue > maxValue)
            throw new ArgumentOutOfRangeException(nameof(minValue), "minValue cannot exceed maxValue");

        if (minValue == maxValue)
            return minValue;

        return (int) (NextUlong() / ((double)ulong.MaxValue / (maxValue - minValue)) + minValue);
    }

    public override int Next()
    {
        return (int) NextLong(0, int.MaxValue + 1L);
    }

    public override int Next(int maxValue)
    {
        return (int) NextLong(0, maxValue + 1L);
    }

    public override int Next(int minValue, int maxValue)
    {
        return (int) NextLong(minValue, maxValue);
    }

    public override void NextBytes(byte[] buffer)
    {
        if (buffer == null)
            throw new ArgumentNullException(nameof(buffer));

        int remaining = buffer.Length;                                 

        while (remaining > 0)
        {
            var next = BitConverter.GetBytes(NextUlong());
            int n = Math.Min(next.Length, remaining);

            Array.Copy(next, 0, buffer, buffer.Length-remaining, n);
            remaining -= n;
        }
    }

    public override double NextDouble()
    {
        return NextUlong() / (ulong.MaxValue + 1.0);
    }

    readonly ulong[] s = new ulong[16];
    int p;
}