C# 关于默认的随机种子,它会在不同的系统中改变吗?
我知道默认的c#Random()是一个伪随机数序列。 我只需要这样一个,我不是在这个问题上寻找真正的随机 请允许我提问: 我试过:C# 关于默认的随机种子,它会在不同的系统中改变吗?,c#,random,C#,Random,我知道默认的c#Random()是一个伪随机数序列。 我只需要这样一个,我不是在这个问题上寻找真正的随机 请允许我提问: 我试过:newrandom(100000000)。接下来(999999999),我得到了145156561,就像一些一样 我的问题是:在不同的系统(win2003、win2008、mono等)、不同的.net版本(.net 3、.net 4、c#2、c#3等)中,相同种子的伪随机数序列是否会发生变化,或者在任何其他环境中是否会发生变化 我想知道的是,一旦我编码了,我会在现在和
newrandom(100000000)。接下来(999999999)
,我得到了145156561,就像一些一样
我的问题是:在不同的系统(win2003、win2008、mono等)、不同的.net版本(.net 3、.net 4、c#2、c#3等)中,相同种子的伪随机数序列是否会发生变化,或者在任何其他环境中是否会发生变化
我想知道的是,一旦我编码了,我会在现在和将来的任何地方,通过相同的种子得到相同的伪随机数序列吗?不可靠。一般来说,解决这类问题的方法是查看文档(MSDN for.NET)。如果该算法未被描述,且不是其他已发布算法的实现,则应将其视为实现细节,并可能发生更改 你也需要非常严格地阅读这些文档——如果有解释的余地,你需要假设最坏的情况。在这种情况下:仅说明: 为不同的随机对象提供相同的种子值会导致 每个实例生成相同的随机数序列 它适用于框架: 在:4、3.5、3.0、2.0、1.1、1.0.NETFramework客户端配置文件中支持 在:4、3.5 SP1可移植类库中支持 在:可移植类库中支持 这并不能说明它是否保证在未来的版本中以相同的方式工作,甚至不能说明您是否能从各种支持的框架中获得相同的结果。事实上,它指出: 来电者须知 随机数发生器在计算机中的实现 随机类不保证在各专业中保持不变 .NET Framework的版本。因此,您的应用程序代码 不应假设相同的种子将产生相同的结果 不同版本的.NET Framework中的伪随机序列
不可靠。一般来说,解决这类问题的方法是查看文档(MSDN for.NET)。如果该算法未被描述,且不是其他已发布算法的实现,则应将其视为实现细节,并可能发生更改 你也需要非常严格地阅读这些文档——如果有解释的余地,你需要假设最坏的情况。在这种情况下:仅说明: 为不同的随机对象提供相同的种子值会导致 每个实例生成相同的随机数序列 它适用于框架: 在:4、3.5、3.0、2.0、1.1、1.0.NETFramework客户端配置文件中支持 在:4、3.5 SP1可移植类库中支持 在:可移植类库中支持 这并不能说明它是否保证在未来的版本中以相同的方式工作,甚至不能说明您是否能从各种支持的框架中获得相同的结果。事实上,它指出: 来电者须知 随机数发生器在计算机中的实现 随机类不保证在各专业中保持不变 .NET Framework的版本。因此,您的应用程序代码 不应假设相同的种子将产生相同的结果 不同版本的.NET Framework中的伪随机序列
实现这一点的最佳方法是实现您自己的随机数生成器。看看实现这一点的最佳方法是实现您自己的随机数生成器。请看一下否,这在不同的.NET版本中适用: Random类的当前实现基于Donald E.Knuth的减法随机数生成器算法 注意单词current的用法;这意味着它可以在框架的更高版本中被替换。(这一点也在合同中明确说明 如果您希望100%确定可以在所有未来版本中复制序列,包括您自己的PRNG,例如。否,这在不同的.NET版本中适用: Random类的当前实现基于Donald E.Knuth的减法随机数生成器算法 请注意单词current的用法;这意味着它可以在框架的更高版本中被替换 如果您想100%确定您可以在所有未来版本中复制序列,请包括您自己的PRNG,例如,根据MSDN的 来电者须知 随机类中随机数生成器的实现 不能保证在.NET的主要版本中保持不变 因此,应用程序代码不应假定 相同的种子将导致相同的伪随机序列 不同版本的.NET Framework 因此,您不能使用
Random
,而依赖于您将获得相同的序列。根据MSDN获得相同的序列
来电者须知
随机类中随机数生成器的实现
不能保证在.NET的主要版本中保持不变
因此,应用程序代码不应假定
相同的种子将导致相同的伪随机序列
不同版本的.NET Framework
因此,您不能使用随机
并依赖于您将获得相同的序列。如图所示:您不能依赖于结果在不同平台上,甚至在.NET的主要版本上是相同的
我们在上遇到了这个问题,因为我们编写了一个使用MonoGame的游戏,它运行在Windows上的.NET中,但当它在OSX中的Mono上运行时产生了不同的值
作为圣
/// <summary>
/// This class is a drop-in replacement to use instead of Random(). Its
/// main purpose is to work identically across multiple platforms for a given
/// seed value - whereas the Random class is not guaranteed to give the
/// same results on different platforms even when the seed is the same.
///
/// This is an implementation of a Linear Congruential Generator which is
/// a very simple pseudorandom number generator. It is used instead of Random()
/// since Random() is implemented differently in Mono than .NET (and even
/// between different major-versions of .NET).
///
/// This is NOT recommended to be used for anything that should be secure such
/// as generating passwords or secret tokens. A "cryptogrpahically secure pseudorandom
/// number generator" (such as Mersenne Twister) should be used for that, instead.
///
/// More about Linear Congruential Generators can be found here:
/// http://en.wikipedia.org/wiki/Linear_congruential_generator
/// </summary>
public class CrossPlatformRandom : Random
{
// To start with, we'll be using the same values as Borland Delphi, Visual Pascal, etc.
// http://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
private const int LCG_MULTIPLIER = 134775813; // 0x08088405
private const int LCG_INCREMENT = 1;
private int _seed;
/// <summary>
/// Initializes a new instance of the CrossPlatformRandom class, using a time-dependent
/// default seed value.
///
/// Please note that this values generated from this are NOT guaranteed to be the same
/// cross-platform because there is no seed value. In cases where the caller requires
/// predictable or repeatable results, they MUST specify the seed.
/// </summary>
public CrossPlatformRandom()
{
// System.Random is time-dependent, so we will just use its first number to generate
// the seed.
Random rand = new Random();
this._seed = rand.Next();
}
/// <summary>
/// Initializes a new instance of the System.Random class, using the specified seed value.
/// </summary>
/// <param name="seed">A number used to calculate a starting value for the pseudo-random number sequence. If a negative number is specified, the absolute value of the number is used.</param>
public CrossPlatformRandom(int seed)
{
_seed = seed;
}
private int GetNext() // note: returns negative numbers too
{
_seed = (_seed * LCG_MULTIPLIER) + LCG_INCREMENT;
return _seed;
}
/// <summary>
// Returns a nonnegative random number.
/// </summary>
/// <returns>A 32-bit signed integer greater than or equal to zero and less than System.Int32.MaxValue.</returns>
public override int Next()
{
return this.Next(int.MaxValue);
}
/// <summary>
/// Returns a nonnegative random number less than the specified maximum.
/// </summary>
/// <param name="maxValue">The exclusive upper bound of the random number to be generated. maxValue must be greater than or equal to zero.</param>
/// <returns> A 32-bit signed integer greater than or equal to zero, and less than maxValue; that is, the range of return values ordinarily includes zero but not maxValue. However, if maxValue equals zero, maxValue is returned.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">maxValue is less than zero.</exception>
public override int Next(int maxValue)
{
if (maxValue < 0)
{
throw new System.ArgumentOutOfRangeException("maxValue is less than zero.");
}
ulong result = (ulong)(uint)GetNext() * (ulong)(uint)maxValue;
return (int)(result >> 32);
}
/// <summary>
/// Returns a random number within a specified range.
/// </summary>
/// <param name="minValue">The inclusive lower bound of the random number returned.</param>
/// <param name="maxValue">The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue.</param>
/// <returns>A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">minValue is greater than maxValue.</exception>
public override int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new System.ArgumentOutOfRangeException("minValue is greater than maxValue.");
}
return minValue + this.Next(maxValue - minValue);
}
/// <summary>
/// Fills the elements of a specified array of bytes with random numbers.
/// </summary>
/// <param name="buffer">An array of bytes to contain random numbers.</param>
/// <exception cref="System.ArgumentNullException">buffer is null.</exception>
public override void NextBytes(byte[] buffer)
{
if (buffer == null)
{
throw new System.ArgumentNullException("buffer is null.");
}
for (int index = 0; index < buffer.Length; index++)
{
buffer[index] = (byte)this.Next((int)byte.MaxValue);
}
}
/// <summary>
/// Returns a random number between 0.0 and 1.0.
/// </summary>
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
public override double NextDouble()
{
return this.Sample();
}
/// <summary>
/// Returns a random number between 0.0 and 1.0.
///
/// Since System.Random no longer uses this as the basis for all of the other random methods,
/// this method isn't used widely by this class. It's here for completeness, primarily in case Random
/// adds new entry points and we are lucky enough that they base them on .Sample() or one of the other existing methods.
/// </summary>
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
protected override double Sample()
{
return ((double)this.Next() / (double)int.MaxValue);
}
}
int seed = 42;
CrossPlatformRandom r = new CrossPlatformRandom(seed);
for (int i = 0; i < 10; ++i)
Console.WriteLine(r.Next(100));