9

Is it possible, from .NET, to mimic the exact randomization that Java uses? I have a seed, and I would like to be able to recieve the same results in both C# and Java when creating a random number.

jason
  • 236,483
  • 35
  • 423
  • 525
George Johnston
  • 31,652
  • 27
  • 127
  • 172
  • And how random is that?... Just asking.. – Filip Ekberg Jan 27 '10 at 14:24
  • @Filip: I think it's implicit that he just wants stochastic randomness. – Will Vousden Jan 27 '10 at 14:26
  • 1
    @Filip: For some things it's imperative that you get the exact results even on multiple runs—simulations for example. You can't just say »Hey, I got these results but you can't reproduce them because they relied on my PRNG having a good day.« – Joey Jan 27 '10 at 14:30

6 Answers6

6

You don't need to read the source code. The formula is a one-liner and is given in the documentation for java.util.Random.

Here's a partial translation:

[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;
}

Example:

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));

Output on both platforms is 0, 3, 18, 4, 20.

finnw
  • 47,861
  • 24
  • 143
  • 221
5

If you have the source code of the java.util.Random class for your Java implementation, you can easily port it to .NET.

If you require both applications (Java and .NET) to use a certain random number generator, you'd better implement one in both platforms and use it instead, as the system provided version might change its behavior as a result of an update.(Looks like the Java specification precisely describes the behavior of its PRNG.)

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • But isn't the algorithm an implementation detail and likely to change between versions/implementations? IMO it would be better to implement a custom algorithm both in Java and C# to get consistent results. – dtb Jan 27 '10 at 14:26
  • @dtb: Was thinking about the same thing. If it's going to be temporary, for testing purposes, that would suffice. Otherwise, yes, you should implement your own. – Mehrdad Afshari Jan 27 '10 at 14:28
  • 4
    @dtb: The algorithm is specified in the documentation of Java's Random class and therefore a specification. Implementation details may change but I highly doubt that the actual sequence generated by it would in a future version. If at all, they're more likely to add a different PRNG in a separate class. But given Java's intended scope and mature libraries out there that actually do a good job for pseudo-random number generation, I doubt that will happen anyway. – Joey Jan 27 '10 at 14:29
  • 1
    The API doc of java.util.Random actually specifies the exact algorithm: http://java.sun.com/javase/6/docs/api/java/util/Random.html#next(int) - not sure whether that is mandated by the official Java compatibility testsuite, though. – Michael Borgwardt Jan 27 '10 at 14:31
2

If you don't need a cryptographically secure pseudorandom number generator then I would go for the Mersenne twister. You can find source code for C# here and Java here.

Jonas Elfström
  • 30,834
  • 6
  • 70
  • 106
  • 1
    That wasn't the question, though. And `java.util.Random` isn't crypographically secure either so that's obviously not h(is|er) concern ;-) – Joey Jan 27 '10 at 14:48
  • 1
    It wasn't the question but since *"mimic the exact randomization that Java uses"* seems hard to impossible to do I focused on *"I would like to be able to recieve the same results in both C# and Java"* instead. – Jonas Elfström Jan 27 '10 at 15:51
0

Well, you can look in the source code for Random.java and copy the algorithm, constants, etc.etc, but Random uses System.nanoTime in its constructor so you won't get the same results.

From java.util.Random

public Random() { this(++seedUniquifier + System.nanoTime()); }

I wouldn't be at all surprised if the source in C# would show you something similar.

Edit: Disregard, as has been pointed out, the constructor that takes an input seed never accesses time.

Steve B.
  • 55,454
  • 12
  • 93
  • 132
  • 2
    He's using the same seed for both, so the default seed in the Java implementation is irrelevant. – Will Vousden Jan 27 '10 at 14:27
  • It only uses it if you don't have a seed, there are 2 constructors `Random()` - Takes nothing and uses `Environment.TickCount` and `Random(int32 num)` that takes your seed instead of the TickCount. – Nick Craver Jan 27 '10 at 14:28
0

Maybe it would make sense to implement your own simple pseudo-random number generator? That way you have complete control and can garauntee the same seed gives the same results in both environments. Probably a bit more work than porting one to the other though.

FrustratedWithFormsDesigner
  • 26,726
  • 31
  • 139
  • 202
-2

Another option might be to write your random numbers out to a file once from one platform and then just load your random numbers for both platforms from that file, or you could load them from a service such as random.org

jk.
  • 13,817
  • 5
  • 37
  • 50