【问题标题】:C#/Java Number RandomizationC#/Java 数字随机化
【发布时间】:2010-01-27 14:21:19
【问题描述】:

是否有可能从 .NET 模仿 Java 使用的精确随机化?我有一个种子,我希望在创建随机数时能够在 C# 和 Java 中获得相同的结果。

【问题讨论】:

  • 那有多随机?...只是问..
  • @Filip:我认为他只想要随机性是隐含的。
  • @Filip:对于某些事情,即使在多次运行(例如模拟)时,您也必须获得准确的结果。您不能只说“嘿,我得到了这些结果,但您无法复制它们,因为它们依赖于我的 PRNG 度过了美好的一天。«

标签: c# java random


【解决方案1】:

您无需阅读源代码。该公式是单行的,在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

【讨论】:

    【解决方案2】:

    如果您有用于 Java 实现的 java.util.Random 类的源代码,则可以轻松地将其移植到 .NET。

    如果您要求两个应用程序(Java 和 .NET)都使用某个随机数生成器,您最好在两个平台上都实现一个并使用它,因为系统提供的版本可能会改变其行为作为更新的结果。(看起来 Java 规范精确地描述了它的 PRNG 的行为。)

    【讨论】:

    • 但是算法不是实现细节并且可能在版本/实现之间发生变化吗? IMO 最好在 Java 和 C# 中实现自定义算法以获得一致的结果。
    • @dtb:正在考虑同样的事情。如果它是临时的,出于测试目的,那就足够了。否则,是的,您应该实现自己的。
    • @dtb:该算法在 Java 的 Random 类的文档中指定,因此是规范。实现细节可能会改变,但我非常怀疑它生成的实际序列是否会在未来的版本中出现。如果有的话,他们更有可能在单独的类中添加不同的 PRNG。但是考虑到 Java 的预期范围和成熟的库,它们实际上在伪随机数生成方面做得很好,我怀疑这无论如何都会发生。
    • java.util.Random 的 API 文档实际上指定了确切的算法:java.sun.com/javase/6/docs/api/java/util/Random.html#next(int) - 不过,不确定这是否是官方 Java 兼容性测试套件规定的。
    【解决方案3】:

    如果您不需要加密安全的伪随机数生成器,那么我会选择 Mersenne twister。您可以找到C# hereJava here 的源代码。

    【讨论】:

    • 不过,这不是问题所在。而且java.util.Random 也不是密码安全的,所以这显然不是 h(is|er) 关心的 ;-)
    • 这不是问题,但由于 “模仿 Java 使用的确切随机化” 似乎很难做到,我专注于 “我想成为能够在 C# 和 Java 中收到相同的结果”
    【解决方案4】:

    好吧,您可以查看 Random.java 的源代码并复制算法、常量等,但 Random 在其构造函数中使用 System.nanoTime,因此您不会得到相同的结果。

    来自 java.util.Random

    公共随机(){ this(++seedUniquifier + System.nanoTime()); }

    如果 C# 中的源代码会显示类似的内容,我一点也不感到惊讶。

    编辑:忽略,正如已经指出的那样,接受输入种子的构造函数永远不会访问时间。

    【讨论】:

    • 他对两者使用相同的种子,所以Java实现中的默认种子是无关紧要的。
    • 它只在你没有种子的情况下使用它,有 2 个构造函数 Random() - 什么都不带并使用 Environment.TickCountRandom(int32 num) 来获取你的种子而不是 TickCount。
    【解决方案5】:

    也许实现您自己的简单伪随机数生成器是有意义的?这样,您就可以完全控制并且可以保证相同的种子在两种环境中都会产生相同的结果。可能比将一个移植到另一个要多一些工作。

    【讨论】:

      【解决方案6】:

      另一种选择可能是将您的随机数从一个平台写入一个文件,然后从该文件加载两个平台的随机数,或者您可以从 random.org 等服务加载它们

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-07
        • 2011-05-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多