0
votes

What do you want to achieve? I want to make a factorial function

What is the issue? I can't find any way to solve factorials unless they are whole numbers

What solutions have you tried so far? I have looked on roblox devforum and youtube and google and discord and I literally can't find any way to get decimals to properly work with factorials

the only thing I know is that you can use gamma functions to solve decimal factorials but I am looking and I have no idea how I would implement that into luau so I am really struggling I even used Stirling's approximation but that is not 100% true as I need something to be completely true to the actual answer

local function SolveFactorial(FN)
    if string.match(FN, "^-") then
        local T = 1
        FN *= -1
        for i = FN, 1, -1 do
            T = T * i
        end
        T *= -1
        return T
    else
        local T = 1
        for i = FN, 1, -1 do
            T = T * i
        end
        return T
    end
end

this is a normal factorial function that works with all integers expect 0

local function SF(FN)
    if string.match(FN, "^-") then
        FN *= -1
        local N = math.sqrt(2*math.pi*FN)*math.pow((FN/math.exp(1)), FN)
        N *= -1
        return N
    else
        local N = math.sqrt(2*math.pi*FN)*math.pow((FN/math.exp(1)), FN)
        return N
    end
end

and this is Stirling's approximation which as I said before isn't 100% accurate

these are the two functions that I have so far and I don't know what I should do at this point to fix it is there a way to use the gamma function or is there an easier way to do this then what I am doing atm

note that this is roblox lua!!!

any help will really save a lot of time thank you, nici

1

1 Answers

0
votes

Your question title is a little misleading, it's not that decimals aren't working. It's that Stirling's Approximation provides inaccurate numbers for your purposes.

If you need a gamma function, there's an implementation on Rosetta Code that's pretty easy to use. I've made small adjustments and transcribed it here :

local function gammafunc(z)
    local gamma = 0.577215664901
    local coeff = -0.65587807152056
    local quad = -0.042002635033944
    local qui = 0.16653861138228
    local set = -0.042197734555571

    function recigamma(rz)
      return rz + gamma * rz^2 + coeff * rz^3 + quad * rz^4 + qui * rz^5 + set * rz^6
    end
     
    if z == 1 then
        return 1
    elseif math.abs(z) <= 0.5 then
        return 1 / recigamma(z)
    else
        return (z - 1) * gammafunc(z - 1)
    end
end

In order to get it to properly return the correct factorial values, you need to offset z by 1.

for n = 0.0, 10, 0.2 do
    local f1 = factorial(n)
    local f2 = stirlingApprox(n)
    local f3 = gammafunc(n + 1)
    print(n, f1, f2, f3)
end
---[[ Returns...
 n             n!            Stirling          Gamma
0.0           1.0000         -0.0000          1.0000
0.2                           0.6652          0.9182
0.4                           0.7366          0.8872
0.6                           0.7843          0.8934
0.8                           0.8427          0.9314
1.0           1.0000          0.9221          1.0000
1.2                           1.0293          1.1018
1.4                           1.1714          1.2421
1.6                           1.3579          1.4295
1.8                           1.6014          1.6765
2.0           2.0000          1.9190          2.0000
2.2                           2.3344          2.4240
2.4                           2.8800          2.9811
2.6                           3.6003          3.7167
2.8                           4.5571          4.6942
3.0           6.0000          5.8362          6.0000
3.2                           7.5579          7.7567
3.4                           9.8914         10.1358
3.6                          13.0759         13.3803
3.8                          17.4518         17.8378
4.0          24.0000         23.5062         24.0000
4.2                          31.9393         32.5781
4.4                          43.7635         44.5977
4.6                          60.4506         61.5492
4.8                          84.1502         85.6217
5.0         120.0000        118.0192        120.0000
5.2                         166.7162        169.4060
5.4                         237.1499        240.8277
5.6                         339.6157        344.6753
5.8                         489.5289        496.6057
6.0         720.0000        710.0782        720.0000
6.2                        1036.3071       1050.3173
6.4                        1521.4128       1541.2974
6.6                        2246.5097       2274.8568
6.8                        3335.8193       3376.9185
7.0        5040.0000       4980.3958       5040.0000
7.2                        7475.3217       7562.2846
7.4                       11278.2406      11405.6005
7.6                       17101.8057      17288.9114
7.8                       26060.2260      26339.9645
8.0       40320.0000      39902.3955      40320.0000
8.2                       61384.0725      62010.7339
8.4                       94864.1090      95807.0442
8.6                      147262.8822     148684.6384
8.8                      229608.1738     231791.6880
9.0      362880.0000     359536.8728     362880.0000
9.2                      565356.8075     570498.7521
9.4                      892663.0429     900586.2158
9.6                     1415149.6282    1427372.5285
9.8                     2252332.9545    2271558.5427
10.0     3628800.0000   3598695.6187    3628800.0000]]

Please keep in mind that this implementation runs the same stackoverflow risk that the traditional factorial function has with larger numbers as it needs to recursively calculate values. The Stirling approximation that you're using is significantly faster and that might be good enough in some cases.