Does dart:math's Random class behave the same on all platforms?

I’m building something with procedural generation, and I’d like the behavior to be consistent across platforms. If I create Random instances using the same seed, will they generate the same sequence of numbers on every platform, including web?

FWIW, that does experimentally seem to be the case across iOS, Android, and web, but I’m wondering if it can be depended upon, and if the pseudorandom number generation algorithm is likely to change across flutter releases.

The implementation for the non-secure random generation are likely implemented similar since they all seems to be based on Multiply-with-carry pseudorandom number generator - Wikipedia, but there are still implemented, at least, in four different versions depending on target platform so I would not depend on them being the same in all situations:

I would regardless strongly suggest to have your own pseudorandom implementation as part of your solution if you are depended on it’s output are fixed across platforms and releases since the implementation of the random generator are not part of the API and can therefore change for any reason.

4 Likes

Fair point - thank you!

AFAIK, there are some crypto-level random generators implemented in pure Dart, as pub packages.

If you just need something pseudorandom and quick, I have been using this:

It implements a very simple Xorshift - Wikipedia and is so simple that is should work the same everywhere (though, now that I think of it, I’m not sure that it does so when compiled to JavaScript — there’s no int in JavaScript).

3 Likes

That’s great, thank you!

(though, now that I think of it, I’m not sure that it does so when compiled to JavaScript — there’s no int in JavaScript)

Yeah, that was one of my main concerns, but your algorithm in particular does this:

// Dart doesn't have uint32 so we have to clamp the number like this.`
x &= _maxInt32;

which I think is going to give us consistent behavior across platforms, including javascript, considering Dart’s documentation on bitwise operators has this to say:

For performance reasons on the web, bitwise (&, |, ^, ~) and shift (<<,>>, >>>) operators on int use the native JavaScript equivalents. In JavaScript, the operands are truncated to 32-bit integers that are treated as unsigned. This treatment can lead to surprising results on larger numbers. In particular, if operands are negative or don’t fit into 32 bits, they’re likely to produce different results between native and web.

Worth some testing to be safe, though.