ios Swift: looking for a cross compatible method to Java's Random() PRNG that has identical output

548 views Asked by At

Here's my delimna: I am writing an application that needs to exactly reproduce the PRNG output from a game that was written in Java that uses the Java random() with a given seed to create all it's initial game 'world' data.

The problem I am facing is that Java's random() and ios Swift native PRNG do not generate the same values when given the exact same seeds.

Here are my test cases: In all cases the same 'seed' is used, and the formula is for a random Integer between 0 and 9.

In Java:

import java.util.Random;
long seed = 987234904;
Random rnd = new Random(seed);
int result = rnd.nextInt(10);

The Java random() 'result' = 0

In ios Swift - using srand48() / drand48():

import UIKit
var seed: Int = 987234904
srand48(seed)
var result = Int(drand48()*10)

The ios Swift drand48() 'result' = 7

In ios Swift - using rand_r():

import UIKit
var seed: UInt32 = 987234904
var result = Int(Float(rand_r(&seed))/Float(INT32_MAX)*10)

The ios Swift rand_r() result = 4

With that in mind - is there a ios Swift|Objective-C|C++ code snippit|library available that is the exact same in functionality and output as the Java's version of random()?

3

There are 3 answers

0
dano On BEST ANSWER

Okay - here is the solve:

I asked the same question in the Apple forums and a nice person by the handle of 'ahltorp' shared a c function that they had been using for the very same thing. It's swift compatible and I have tested it against my simulation and it's a flawless match of data!

Github location of the C function: https://github.com/ahltorp/swiftjavarandom

Swift example to use it

var inseed: UInt64 = 987234904   
java_random_setseed(&inseed, inseed)  
var result = java_random_nextint_n(&inseed, 10)  
print(result) 

Result = 0 :-)

Link to the apple forum discussion: https://forums.developer.apple.com/thread/5791?q=Swift%20prng

2
Kametrixom On

No, that's not possible (most likely), because implementations of random don't even need to be constant through different versions and systems, you'd have to implement your own random algorithm to be sure. Or you could generate a sequence, save it and somehow transfer it to the other device, but that's a whole lot more complicated.

Have a look at the EXAMPLE section in this link which gives an algorithm and states that this could be useful for two different machines:

static unsigned long next = 1;

/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

void mysrand(unsigned seed) {
    next = seed;
}

You just have to translate it into the preferred language

1
rickster On

In iOS 9 and OS X 10.11, GameplayKit provides a suite of deterministic PRNGs — one of the primary rationales being so that you can replicate a random sequence across multiple devices or between server and client for multiplayer games. (See the WWDC session for more rationale and other fun stuff.)

In particular, GKLinearCongruentialRandomSource uses the Knuth standard and should thus be compatible with java.util.Random (when initialized with the same 48-bit seed, of course).