gpt4 book ai didi

c# - System.Random 会始终为跨平台的给定种子生成可预测的数字吗?

转载 作者:太空狗 更新时间:2023-10-29 19:56:50 26 4
gpt4 key购买 nike

我知道 Object.GetHashCode 可以根据平台为同一对象(例如,相同的字符串)返回不同的值。因此,我不能依赖它来获得跨平台的简单哈希。

但是我可以依赖 System.Random 吗?无论我是否使用 Microsoft .NET/Mono/x86/x64 等,它都会为给定的种子产生相同的结果吗?

最佳答案

正如 Jeremy 提到的 in his answer文档指出,不能保证数字生成器在 .NET 版本之间保持一致。

但是,文档还告诉您how to implement your algorithm too .

You can implement your own random number generator by inheriting from the Random class and supplying your random number generation algorithm. To supply your own algorithm, you must override the Sample method, which implements the random number generation algorithm. You should also override the Next(), Next(Int32, Int32), and NextBytes methods to ensure that they call your overridden Sample method. You don't have to override the Next(Int32) and NextDouble methods.

使用它,我们可以制作我们自己的随机类,该类使用您可以使用的已知固定算法。例如,我们可以去 to the .Net source并实现当前的随机算法,这将允许我们使用 ConsistantRandom 类并确定该算法不会改变我们。

以下示例源自the .NET Core 1.1.0 source .

using System;

namespace ConsoleApplication1
{
public class ConsistantRandom: Random
{
private const int MBIG = Int32.MaxValue;
private const int MSEED = 161803398;
private const int MZ = 0;

private int inext;
private int inextp;
private int[] SeedArray = new int[56];

public ConsistantRandom()
: this(Environment.TickCount)
{
}

public ConsistantRandom(int seed)
{
int ii;
int mj, mk;

int subtraction = (seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(seed);
mj = MSEED - subtraction;
SeedArray[55] = mj;
mk = 1;
for (int i = 1; i < 55; i++)
{
ii = (21 * i) % 55;
SeedArray[ii] = mk;
mk = mj - mk;
if (mk < 0) mk += MBIG;
mj = SeedArray[ii];
}
for (int k = 1; k < 5; k++)
{
for (int i = 1; i < 56; i++)
{
SeedArray[i] -= SeedArray[1 + (i + 30) % 55];
if (SeedArray[i] < 0) SeedArray[i] += MBIG;
}
}
inext = 0;
inextp = 21;
}
protected override double Sample()
{
return (InternalSample() * (1.0 / MBIG));
}

private int InternalSample()
{
int retVal;
int locINext = inext;
int locINextp = inextp;

if (++locINext >= 56) locINext = 1;
if (++locINextp >= 56) locINextp = 1;

retVal = SeedArray[locINext] - SeedArray[locINextp];

if (retVal == MBIG) retVal--;
if (retVal < 0) retVal += MBIG;

SeedArray[locINext] = retVal;

inext = locINext;
inextp = locINextp;

return retVal;
}

public override int Next()
{
return InternalSample();
}

private double GetSampleForLargeRange()
{
int result = InternalSample();
bool negative = (InternalSample() % 2 == 0) ? true : false;
if (negative)
{
result = -result;
}
double d = result;
d += (Int32.MaxValue - 1);
d /= 2 * (uint)Int32.MaxValue - 1;
return d;
}


public override int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentOutOfRangeException("minValue");
}

long range = (long)maxValue - minValue;
if (range <= (long)Int32.MaxValue)
{
return ((int)(Sample() * range) + minValue);
}
else
{
return (int)((long)(GetSampleForLargeRange() * range) + minValue);
}
}
public override void NextBytes(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException("buffer");
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)(InternalSample() % (Byte.MaxValue + 1));
}
}
}

}

因为 ConsistantRandom 派生自 Random 您可以使用该类作为替换任何您之前拥有 Random 类型的地方,您只需要将 Random rnd = new Random(yourSeed); 替换为 Random rnd = new ConsistantRandom(yourSeed);

关于c# - System.Random 会始终为跨平台的给定种子生成可预测的数字吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42823244/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com