Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
3

Random.new or math.random, which is superior?

Asked by 6 years ago

Which is better for constructing random object from a seed?


Lately, I have seen a brief discussion on the discord server about which is the best random number generator available on roblox. One person advised someone to use math.randomseed(tick()) and then do math.random(). However, another user said that Random.new() should be used instead of math.randomseed(). So, after I did a quick search on the wiki, I couldn't really discern the difference between math.randomseed and Random.new().

Any differences between :NextInteger(min,max) and math.Random(min,max)?


So after researching Random.new, Random:NextInteger, and Random:NextNumber for a bit I am still confused about why, if both methods provide psuedo-random numbers, why have two ways to perform the same task. For example, the following two bits of code should generate psuedo-random integers between 0 and 200

local random = Random.new(tick())
while true do
    print(random:NextInteger(0,200))
    wait(2)
end

and

math.randomseed(tick())
while true do
    print(math.random(0,200))
    wait(2)
end

These two pieces of code should, essentially do the same thing, that being generating a psuedo-random number between 0 and 200. But that still raises the question of why, why have two different ways to accomplish the same thing?

So, if anyone has any idea of what the rationale behind having two ways of essentially doing the same thing, and if there is a different, which of the two methods is better, or "Random-er" than the other, that would be appreciated.

0
math.random follows the same algorithm as Random.new now, but Random has its own benefits nonetheless. User#19524 175 — 6y
1
Biggest benefit of Random as far as I'm concerned - Random datatype includes the seed in its creation. If we set math.randomseed(tick()) - then throughout the whole script this will be the seed for math.random; however, with Random - we can do a = Random.new(seed1) AND b = Random.new(seed2) -- if we needed two separate pseudorandom number gens for whatever reason. SummerEquinox 643 — 6y

1 answer

Log in to vote
2
Answered by 6 years ago

The TLDR is that Random.new() is better, and there is no reason to use math.random() ever, as it has no benefits and a significant drawback if you're trying to do something with a repeatable, deterministic random sequence.

Internally, math.random() used to use good old C rand(). Which was not actually good, in any way, and the generator was shared by everything running in the Roblox client or Studio: your code, Roblox's Lua code, Studio C++ code... so seeding the thing was completely and utterly pointless.

Now, math.random() just internally calls the PRNG implemented by the new Random class. This was done to retroactively improve the statistical randomness of math.random() for the benefit of games that are already using it. This does not mean you should use it for new work. This re-implementation of math.random() using Random does not address the other major shortcoming which is the single shared generator. If you use math.random(), all your code that calls it is still pulling from the same stream, so it's very difficult to get repeatable results even if you seed it with the same number. Any variation in the order with which scripts or coroutines call math.random() can make the behavior change from run to run. It only takes one extra or one out of order call to get a completely divergent behavior from that point on.

The other thing that Random.new() has over math.random() is that math.random() now has conditional logic overhead to redirect to Random's functions. You can call math.random() with no arguments, one argument, or two, and the behavior is different. On the C++ side, it's counting the arguments and doing if-then-else branching to decide which function of Random to call. This overhead is very tiny, almost negligible, but it's there, and when you have two options to use that get you the same values, why would you knowingly call the less efficient one?

Ad

Answer this question