Factorial Caculator in Lua with Explanation

Today, we are going to be making a factorial calculator but first…

What is a factorial?

A factorial is the product of a number and the numbers below it (not including 0 and negative numbers)

Examples

What is 4 factorial? In order to find out, you have to multiply 4 (the number) by 3, 2, and 1 (the numbers below it). Your product should be 24.

Coding Part

Now, let’s make our calculator. Firstly, we need type what number we are going to calculate the factorial of. In this example, we are going with 4.

local n = 4 -- you can always change this number

Now we have to find the numbers below 4 and find the product of them.

local product = 1

for number = 1, n-1 do
	product = product * number
end

Lastly, we have to get our final result by multiplying the number and the first product together. Then, we print the result.

-- Final calculation and print
local final_result = product * n
print("The factorial of", n, "is:", final_result)

That’s all! If you want to want a video, you can watch it here.

2 Likes

Or make it a simple function

function factorial(n)
    if n == 0 then
        return 1
    else
        return n * factorial(n - 1)
    end
end
7 Likes

What are use cases of factorial? I’ve never had a situation where I needed one, and I’ve been coding for 4 years.

5 Likes

Or even shorter

local function factorial(n)
	return n == 1 and 1 or n * factorial(n - 1)
end
2 Likes

None, it is just a simple coding exercise, and a good way to see if the programming language you made in 2 days is actually turing complete

--!native

local function factorial(number: number): (number)
	if number < 0 or number ~= number then
		return 0/0
	end
	
	local result = 1
	
	for i = 2, number do
		if result == math.huge then
			return result
		end
		
		result *= i
	end
	
	return result
end

This function is extremely fast, even when dealing with infinity. It handles negative numbers, extremely large numbers, and undefined numbers efficiently and respectively. When getting a twenty factorial, it can be done 10,000 times in 0.0007 seconds.

The only downside is it doesn’t respect decimals. Roblox has no gamma function and implementing my own made it extremely slow. I posted it below but beware, it’s slow and not entirely accurate.

--!native

-- factorial(x) = gamma(x + 1)

local function gamma(x: number): number
	local function f(t)
		return math.exp(-t) * t^(x-1)
	end
	
	local sum2 = 0
	local sum3 = 0
	
	for i = 1, 9999, 2 do
		sum2 += f(i*0.01)
	end
	
	for i = 2, 9998, 2 do
		sum3 += f(i*0.01)
	end
	
	return 0.0033333333333335 * (f(0) + f(100) + 4*sum2 + 2*sum3)
end

They are both simple, though one uses for loop, and yours uses recursion. However, when it comes to performance, the for loop example is significantly faster as it doesn’t use recursion, which is not optimized by Luau, because the compiler doesn’t implement tail call optimization. Additionally, if you memoize the function, it will give additional performance boost (from about 1ms you can get down to nearly 1 microsecond).

Benchmark:

RobloxStudioBeta_91GNfdI8RI

recursive_factorial: 5.100ms
for_loop_factorial: 0.978ms
memoized_for_loop_factorial: 0.003ms

Source Code
--!strict
--!native
--!optimize 2

local memoized = {}
local function memoized_for_loop_factorial(n: number): number
	if memoized[n] then
		return memoized[n]
	end
	local result = 1
	for i = 2, n do
		result *= i
	end
	memoized[n] = result
	return result
end

local function for_loop_factorial(n: number): number
	local result = 1
	for i = 2, n do
		result *= i
	end
	return result
end

local function recursive_factorial(n: number): number
	if n == 0 then
		return 1
	else
		return n * recursive_factorial(n - 1)
	end
end

local N = 1000

return {
	ParameterGenerator = function()
		return
	end,

	Functions = {
		["memoized_for_loop_factorial"] = function(_)
			local _t
			for i = 1, N do
				_t = memoized_for_loop_factorial(i)
			end
		end,

		["for_loop_factorial"] = function(_)
			local _t
			for i = 1, N do
				_t = for_loop_factorial(i)
			end
		end,
		
		["recursive_factorial"] = function(_)
			local _t
			for i = 1, N do
				_t = recursive_factorial(i)
			end
		end,
	},
}

Those numbers will not matter that much if you are occasionally running the function, but if it’s vital to math heavy module (such as for Bézier curves), it will make a drastic difference.

From what I’ve seen, it’s mostly math heavy modules that use them. For example, one of the Bézier curve modules I use, utilizes Bernstein Polynomial which depends on factorial function.

local function bernstein_polynomial(n: number, i: number, t: number): number
	return (factorial(n) / (factorial(i) * factorial(n - i))) * t^(i) * (1 - t)^(n - i)
end
1 Like

There actually exists a (in my opion) better factorial formula that extends it to non-integers, and in my opinion, is actually really elegant! You just have to plug a high value for N, and you have an extended definiton for factorials! Here it is:


If you’re confused about the pi symbol a bit, that just means you’re starting at k=1, and multiply it by itself except k=2, and then multiply by itself except k=3, and so on until k=N, and since N is meant to get bigger and bigger until it reaches “infinity”, that process will never end. Of course we can’t handle a non-terminating process, but we can get close to it. If we set N=10,000, we will get a VERY close result to the actual factorial function.
Now, we can code this pretty easily in Lua, just use a for loop and stuff.
Also, this also works for negative numbers as well, just set x to a negative number. BUT, there’s a catch.
This does not work for negative whole numbers.
Why?
If you try using the original definition of the factorial you will end up that to get the previous factorial, for example I’ll just use that 4!=24 and find 3! using that method. To get the previous factorial, you have to divide by the number you are taking the previous factorial of.
Example: 4!=24, so divide by 4.
24/4=6
So 3! is 6, which is indeed the correct answer!
However, if you try this using that 0!=1, you have to divide by 0, which you cannot do.
So that’s why I said this doesn’t work for negative whole numbers.
I don"t think negative factorials have a use though, (atleast one that I know of)
So yeah, the product formula is my favourite extension of my factorials for non-integers!
And there’s something bonus about it!
This formula actually gives the correct value for x!, not (x-1)!
Edit: I implemented the formula onto Lua!

factorial = 5 -- number you want to approximate the factorial of
approx = 1000000 -- higher values lead to more accurate results
temp = 1 -- dont change this
for i = 1, approx do
	temp = temp * (i/(factorial + i))
end
wait(0)
result = approx^factorial * temp
print("Result = " .. result)

Here’s the .rbxl file:
factorial.rbxl (44.9 KB)

2 Likes