Math.random(0,10) vs Random.new():NextNumber(0,10)

I recently just learned that the Random class was a thing

Let’s say, for example, I wanted to generate a random number between one and ten. I could do either of the following:

--// Option A
print(math.random(1,10)

--// Option B
local RandomObj = Random.new()
print(RandomObj:NextInteger(1,10))

I’m wondering what are the pros and cons of each option, and which would technically be more “random”

Thanks in advance

4 Likes

math.random and Random internally use the same algorithm, so the only difference is that with Random you can create different instances while with math.random you always use the same instance.

3 Likes

Both are fine. But you probably shouldn’t be doing Random.new():NextNumber(0,10) like you suggested in your title. Each successive call of NextInteger (or similar) to a Random object is supposed to generate “good” pseudorandom numbers. There’s no guarantee that a sequence of the first calls to newly created Random objects has the same properties, i.e. you might get “bad” sequences.

Testing the distribution tho it seems fine:

local t = {}
local rolls = 10000000
for i = 1, rolls do
	local n = Random.new():NextInteger(1, 10)
	t[n] = (t[n] or 0) + 1
end

for k, v in pairs(t) do
	print(k, (v/rolls) * 10)
end

=>

  1 1.001109
  2 1.001402
  3 0.998534
  4 0.999867
  5 0.99977
  6 1.002493
  7 0.999089
  8 0.998426
  10 0.998571
  9 1.000739

Everything is close to 1, as it should be.

The one big advantage of Random is that you can have different RNGs with different states, which is useful if you’re trying to generate the same sequence of numbers from the same seed.

1 Like

math.random() for quick and easy access to a random value
Random.new() for a better random for the script environment its used in.

I guess you could look at it this way too: math.random() is global and Random.new() is local.

I find Random.new()'s outcome “feels better” than math.random, even if they use the same algorithm internally.

3 Likes

Just a heads-up, you don’t have to call Random.new() multiple times, noting that it is a random number generator. Setting it as a variable is better than getting a new generator every single time, unless you want to refresh the seed. Treat it like an object and use its functions as the equivalent of math.random(), not math.randomseed().

2 Likes

As the above person mentioned, you only really need to call Random.new() once per script.

This is what I end up doing most of the time:

local newRandom = Random.new()
local function random(a, b)
	return newRandom:NextInteger(a, b)
end

print(random(1,10))
2 Likes