What's the point of Random.new():NextNumber()? Random vs. math.random()?

I’m curious about the main differences between the 2.

I’m using Random.new() because I heard it’s better to use, but is there an actual difference?

-- in a module so I don't have to type that all out EVERY time
function utilities.random(m, n)
    return Random.new():NextNumber(m, n)
end
2 Likes

Well yes Random object does provide a lot of useful functions so it’s better than math.random. I’ve heard some people say that Random.new is more random than math.random but according to this post

math.random was updated.

The feature was shown here:


Random clearly has a better algorithm compared to math.random()

Do not use Random.new():NextNumber(m, n) every function call. You’re supposed to only seed once because otherwise the “randomness” isn’t given and will fail respective tests.

local randGen = Random.new()
function utilities.random(m, n)
    return randGen:NextNumber(m, n)
end
2 Likes

This code wouldn’t be okay?

function utilities.random(m, n)
    return Random.new(os.clock() * 1000):NextInteger(m, n)
end

It wouldn’t. Random.new() should be separate into a new variable. You don’t want to call it multiple times or it will certainly cost some resources.

I see, thank you.

Updated Code:

local RandomSeed = Random.new(os.clock() * 1000) -- is this better?
function utilities.random(m, n)
    return RandomSeed:NextInteger(m, n)
end
2 Likes

The Random object and math.random share the same algorithm. The Random object is good for holding state and branching results however, which the math.random object doesn’t do. Seeding is global to all uses of math.random, whereas Random objects can have their own seed.

Passing a seed in the constructor is only necessary if you need deterministic randomisation where the results of each iteration are the same, otherwise leave it blank. The seed will automatically be randomised from a source of entropy for every new Random object, it is not necessary for you to do that.

For example: if you needed Random results but you wanted the pattern the same, you could pass a seed of 500. Every time you make a new Random object and pass 500, the generation pattern will be the same. If it generates 5, 9, 1, 3 and say 20 minutes later you make another Random object with the 500 seed, it will also return 5, 9, 1, 3.

Random gives you the ability to effectively make randomisation local to that object, whereas math.random is global. If seeding is irrelevant and you aren’t making much or any use of math.randomseed, you can continue to use math.random. If you’re looking for more options, use the Random object.

In your case of generation, you can just directly use the Random object and avoid wrapping it in a function, really not that necessary to include your own function in your utilities module. That being said, what you’re doing now is no different than simply just using math.random. If you want to retain the seed you’ll need to return a function. At the very least, you won’t be creating a new Random object every time, but you won’t be globalising the seed either.

--- Optionally add a parameter for seeding if you require it
function utilities.getRNG()
    local RandomGenerator = Random.new()

    return function(min, max)
        return RandomGenerator:NextInteger(min, max)
    end
end

local generateRandomNumber = utilities.getRNG()
local newNumber = generateRandomNumber(1, 10)
8 Likes