是否可以从.NET模仿Java使用的确切随机化?我有一个种子,我希望能够在创建随机数时在C#和Java中收到相同的结果。
答案 0 :(得分:6)
您无需阅读源代码。公式是单线程,在documentation for java.util.Random
.
以下是部分翻译:
[Serializable]
public class Random
{
public Random(UInt64 seed)
{
this.seed = (seed ^ 0x5DEECE66DUL) & ((1UL << 48) - 1);
}
public int NextInt(int n)
{
if (n <= 0) throw new ArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)Next(31)) >> 31);
long bits, val;
do
{
bits = Next(31);
val = bits % (UInt32) n;
}
while (bits - val + (n - 1) < 0);
return (int) val;
}
protected UInt32 Next(int bits)
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (UInt32)(seed >> (48 - bits));
}
private UInt64 seed;
}
示例:
Random rnd = new Random(42);
Console.WriteLine(rnd.NextInt(10));
Console.WriteLine(rnd.NextInt(20));
Console.WriteLine(rnd.NextInt(30));
Console.WriteLine(rnd.NextInt(40));
Console.WriteLine(rnd.NextInt(50));
两个平台上的输出均为0, 3, 18, 4, 20
。
答案 1 :(得分:5)
如果您的Java实现具有java.util.Random
类的源代码,则可以轻松地将其移植到.NET。
如果您需要两个应用程序(Java和.NET)使用某个随机数生成器,您最好在两个平台中实现一个并使用它,因为系统提供的版本可能会将其行为更改为更新的结果。(看起来Java规范准确地描述了其PRNG的行为。)
答案 2 :(得分:1)
如果您不需要加密安全的伪随机数生成器,那么我会选择Mersenne twister。您可以找到C# here和Java here的源代码。
答案 3 :(得分:0)
好吧,你可以查看Random.java的源代码并复制算法,常量等等,但Random在其构造函数中使用System.nanoTime,这样你就不会得到相同的结果。
来自java.util.Random
public Random(){ 这个(++ seedUniquifier + System.nanoTime()); }
如果C#中的源代码会显示类似内容,我一点都不会感到惊讶。
编辑:忽略,正如已经指出的那样,接受输入种子的构造函数永远不会访问时间。
答案 4 :(得分:0)
实现自己的简单伪随机数生成器可能有意义吗?通过这种方式,您可以完全控制并且可以获得相同的种子,从而在两种环境中都能获得相同的结果。可能比将一个移植到另一个更多的工作。
答案 5 :(得分:-2)
另一种选择可能是将随机数从一个平台写入文件,然后只从该文件加载两个平台的随机数,或者您可以从random.org等服务加载它们