How to calculate the 21! (21 factorial) in swift?
Did you think about using a double perhaps? Or NSDecimalNumber?
Also calling the same function recursively is really bad performance wise.
How about using a loop:
let value = number.intValue - 1
var product = NSDecimalNumber(value: number.intValue)
for i in (1...value).reversed() {
product = product.multiplying(by: NSDecimalNumber(value: i))
}
func factorial(_ n: Int) -> Double {
return (1...n).map(Double.init).reduce(1.0, *)
}
(1...n)
: We create an array of all the numbers that are involved in the operation (i.e:[1, 2, 3, ...]
).map(Double.init)
: We change fromInt
toDouble
because we can represent bigger numbers with Doubles than with Ints (https://en.wikipedia.org/wiki/Double-precision_floating-point_format). So, we now have the array of all the numbers that are involved in the operation asDoubles
(i.e:[1.0, 2.0, 3.0, ...]
).reduce(1.0, *)
: We start multiplying1.0
with the first element in the array (1.0*1.0 = 1.0
), then the result of that with the next one (1.0*2.0 = 2.0
), then the result of that with the next one (2.0*3.0 = 6.0
), and so on.
Step 2 is to avoid the overflow issue.
Step 3 is to save us from explicitly defining a variable for keeping track of the partial results.
Here's a function that accepts any type that conforms to the Numeric
protocol, which are all builtin number types.
func factorial<N: Numeric>(_ x: N) -> N {
x == 0 ? 1 : x * factorial(x - 1)
}
Unsigned 64 bit integer has a maximum value of 18,446,744,073,709,551,615. While 21! = 51,090,942,171,709,440,000. For this kind of case, you need a Big Integer type. I found a question about Big Integer in Swift. There's a library for Big Integer in that link.
BigInteger equivalent in Swift?