How to make a weighted random number generator including decimals?

Basically, I’m trying to make a random number generator, but it has a preference toward certain numbers.

For example, if lets say I put the

Min: 1
Max: 10
Preferred Number: 2
Weight: 3 (This number influences how often it will be the preferred number)

How would I make it so it will still be able to get numbers like 1 and 10, but the preferred number will appear more often depending on the weight?

ALSO, how would I accomplish this with decimals in between the min and max?

So if the preferred number is 2, numbers like 1.5 through 2.5 would also appear more frequently.

1 Like

If you are trying to do something like “common: 30%” then I recommend setting the minimum to 1 and max to 100, then if the number is between 1 and 30, then you know it is common.

As for decimals, I don’t think you can do this because then you can get numbers like 2.39387272929736272929272636 which can be memory heavy.

You are looking for a skewed random number generator. Random Number Generators (RNG)s, by definition, are uniformly distributed (they are supposed to be anyways). You are looking for an RNG that peaks at 2, or any number you give it. If you just wanted integers, you could do something like this:

local function weightedRandom(min, max, pref, weight)
	-- Setup
	local rand = Random.new()
	local numberTab = {}

	-- Generate Number Table
	for i = min, max, 1 do
		if i == pref then
			for j = 1, weight, 1 do
				table.insert(numberTab, pref)
			end
		elseif i == (pref - 1) then
			for j = 1, math.floor(pref / 2), 1 do
				table.insert(numberTab, pref - 1)
			end
		elseif i == (pref + 1) then
			for j = 1, math.floor(pref / 2), 1 do
				table.insert(numberTab, pref + 1)
			end
		else
			table.insert(numberTab, i)
		end
	end

	-- Pick number and return it.
	return rand:NextInteger(1, #numberTab)
end

If you want to include floating point numbers, that is not really feasible to do in LUA with any kind of performance. You need to use either C or ASM to be able to do that.

Don’t use math:random() as that’s a linear congruential generator. You can use the Random class. It has a method called NextNumber() that will give you floating point numbers.

2 Likes