A New Random Library

You may have noticed that math.random() doesn’t do much, and there could be certain circumstances where you need a specific type of random. Random.new() has more features but sometimes you may need more. This is why I want to give you guys a more advanced random number generator.

The first feature is super simple. It just returns exactly what Roblox would return. I added this so that you wouldn’t need to use math.random() or Random.new() again.

RandomUtility = {}
function RandomUtility.new(m,n)
	if tonumber(m) then
		return Random.new():NextInteger(m,n)
	else
		return m[Random.new():NextInteger(1,#m)]
	end
end

RandomUtility.new(1,10) --returns random number from 1-10

You can also return keys from tables using this.

local fruits = {"Apple","Banana","Orange","Pineapple"}
RandomUtility.new(fruits) --returns random fruit

And lastly you can specify which integers to include and exclude

local Numbers = {1,3,6,9,11}
RandomUtility.new(Numbers) --Only returns odd numbers

The second feature that I want to show is it’s ability to evade duplicates using the RandomUtility.shuffle() function. Obviously when something is random, there’s a chance that it may repeat, even if the chances are low.

You can stop that problem with this function:

RandomUtility = {}
function RandomUtility.shuffle(m,n,_dataTable)
	local _table
	local function returnRandom(a,b,c)
		if not _dataTable then
			_table=a;c=b;b=#a;a=1
		end	
		local rand = Random.new():NextInteger(a,b)
		repeat
			rand = Random.new():NextInteger(a,b)
			wait()
		until (not c[rand])
		c[rand] = true
		if b == #c then
			for i, int in ipairs(c) do
				if int == true then
					table.clear(c)
					c[rand] = true
				end
				wait()
			end
		end	
		if _dataTable then
			return rand
		else
			return _table[rand]
		end	
	end	
	if tonumber(m) then
		return returnRandom(m,n,_dataTable)
	else
		return returnRandom(m,n)
	end
end

After you have that base, you can simply do something like this to stop duplicates one after another.

local save = {} --Data gets stored inside a table so you need to give it an empty table to work with
RandomUtility.shuffle(1,10,save) --Stops numbers from repeating twice. For example, would return something like 3,1,6,9 instead of 3,1,1,6

NOTE: This isn’t very efficient with large numbers because as you generate more and more numbers, the chance that you encounter a new number goes down, and this script repeats random until it finds a new one. So if you did something like Random.shuffle(1,10000,save), There would be a 1 in 10000 chance to generate a new number, and the way that it finds new numbers is that it generates them randomly. I’m currently working on a more efficient shuffle, and any recommendations on how to go about this would be appreciated.

You can also get a random shuffle with keys in tables. This stops the same key from returning.

local save = {}
local fruits = {"Apple","Banana","Orange","Pineapple"}
RandomUtility.shuffle(fruits,save)

Once again, this also means that you can make a table of integers to specify which integers to include and exclude.

local save = {}
local Numbers = {2,4,6,8,10}
RandomUtility.shuffle(Numbers,save) --Only returns even numbers

The last thing that I want to show is RandomUtility.precise(). You may notice that if you do math.random(0,0.5) or Random.new():NextInteger(0,0.5), it will always return 0. The reason is because math.random only allows for whole integers. With RandomUtility.precise(), you can get decimals up to the 100000000th point. The code for that is:

RandomUtility = {}
function RandomUtility.precise(m,n,decimalPlaces)
	if decimalPlaces then
		local num = math.clamp(decimalPlaces,0,8)
		local rand = Random.new():NextInteger(m*10^num,n*10^num)
		return rand/10^num
	else
		local rand = Random.new():NextInteger(m*10^8,n*10^8)
		return rand/10^8
	end
end

RandomUtility.precise(1,10,5) --Returns a random value from 1-10 with 5 decimal points after the whole number. Example: 5.12345 instead of 5
RandomUtility.precise(0,0.5,3) --Example: Would return 0.255 instead of 0

Those are all of the features that I currently added. If you have any recommendations for another type of random to add, optimization, etc, then please let me know. Also PLEASE tell me if you encounter any bugs and if there are any errors in this topic. Other than that, thank you for reading.

WHOLE CODE:

RandomUtility = {}

function RandomUtility.new(m,n)
	if tonumber(m) then
		return Random.new():NextInteger(m,n)
	else
		return m[Random.new():NextInteger(1,#m)]
	end
end

function RandomUtility.shuffle(m,n,_dataTable)
	local _table
	local function returnRandom(a,b,c)
		if not _dataTable then
			_table=a;c=b;b=#a;a=1
		end	
		local rand = Random.new():NextInteger(a,b)
		repeat
			rand = Random.new():NextInteger(a,b)
			wait()
		until (not c[rand])
		c[rand] = true
		if b == #c then
			for i, int in ipairs(c) do
				if int == true then
					table.clear(c)
					c[rand] = true
				end
				wait()
			end
		end	
		if _dataTable then
			return rand
		else
			return _table[rand]
		end	
	end	
	if tonumber(m) then
		return returnRandom(m,n,_dataTable)
	else
		return returnRandom(m,n)
	end
end

function RandomUtility.precise(m,n,decimalPlaces)
	if decimalPlaces then
		local num = math.clamp(decimalPlaces,0,8)
		local rand = Random.new():NextInteger(m*10^num,n*10^num)
		return rand/10^num
	else
		local rand = Random.new():NextInteger(m*10^8,n*10^8)
		return rand/10^8
	end
end
8 Likes

This is a nice utility, but there is already a RNG class built into Roblox called Random - perhaps you should change the name to something like “RandomUtility” ?

Also - I’d recommend using the Random class for your random generation, it’s much better than the math.random function.

4 Likes

Thanks for letting me know. I’ll add it ASAP

Also I forgot to thank @DrKittyWaffles for the shuffle code. It was heavily based off of what he did