Factorials in Swift

6.8k views Asked by At

I need a good factorial function. The one I have written here works entirely, except when n gets far too large. This is for a calculator app, and I can return 0 / 0 for values that cannot be factorialed because I have an error checker that will declare that as impossible. However performing the function on a very large number crashes the app. I can't use a range operator because my types are doubles.

func factorial(n: Double) -> Double {
    if n >= 0 {
        return n == 0 ? 1 : n * self.factorial(n - 1)
    } else {
        return 0 / 0
    }
}

What is the best way to do this?

2

There are 2 answers

1
Duncan C On BEST ANSWER

As others have said you can use libraries that support larger numbers, or just don't allow values that are too big.

Note that if you want to handle very large values you might need to use a loop rather than a recursive algorithm because recursion can cause a Stack Overflow. Yes, that's right, an SO "eponymous crash".

To prevent numbers that are too big, figure out the largest number that doesn't crash, and do input checking and reject numbers bigger than that.

You can figure out the number that crashes it by going in the opposite direction and logging the count and the result every 10 steps:

1 * 2 * 3 * 4 * 5 * 6...

When you crash, go back to the previous largest logged value, start from there plugging in your previously logged factorial result, and step 1 at a time until you crash. Then only allow n that's 1 less than your crash value.

0
Adam Freeman On

Here is a simple non-recursive function in Swift -~`~~-^>>

public func factorial(_ N: Double) -> Double {
    var mult = N
    var retVal: Double = 1.0
    while mult > 0.0 {
        retVal *= mult
        mult -= 1.0
    }
    return retVal   
}

Caveat: this function only works for doubles >= 0.0 and zero mantissa