18

I am making fuction that calculate factorial in swift. like this

func factorial(factorialNumber: UInt64) -> UInt64 {
    if factorialNumber == 0 {
        return 1
    } else {
        return factorialNumber * factorial(factorialNumber - 1)
    }
}

let x = factorial(20)

this fuction can calculate untill 20.

I think factorial(21) value bigger than UINT64_MAX.

then How to calculate the 21! (21 factorial) in swift?

dialektike
  • 411
  • 1
  • 5
  • 7
  • I think this isn't possible in pure Swift. At least not trivial. I don't know any language that can calculate such numbers out of the box. – dasdom Nov 12 '15 at 07:31
  • I haven't used it personally, but you can try a library like such as https://github.com/kirsteins/BigInteger – Kevin Nov 12 '15 at 07:32
  • It might be ugly, but if you store the result of each iteration in a string instead of a UIint, you can multiple it like it was in paper. Not efficient, the BigInteger library looks more useful, but this is an option too. – Dániel Nagy Nov 12 '15 at 07:36
  • what for do you need the factorial ? if it is a part of equation (like in some division) then you can compute the equation in iterative steps keeping the subresults small enough to fit into variable. Another way is use `H,L` style variables (2 variables per single number) or use bigint lib of some kind. If you go for bigints then may be this [Fast exact bigint factorial](http://stackoverflow.com/a/18333853/2521214) could help a bit – Spektre Nov 12 '15 at 07:57
  • @dasdom allmost any dialect of Smalltalk would compute 21! out of the box – aka.nice Nov 12 '15 at 16:48
  • 1
    @dasdom: Python, too. – Mark Dickinson Nov 12 '15 at 19:13

10 Answers10

13
func factorial(_ n: Int) -> Double {
  return (1...n).map(Double.init).reduce(1.0, *)
}
  1. (1...n): We create an array of all the numbers that are involved in the operation (i.e: [1, 2, 3, ...]).

  2. map(Double.init): We change from Int to Double 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 as Doubles (i.e: [1.0, 2.0, 3.0, ...]).

  3. reduce(1.0, *): We start multiplying 1.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.

kanobius
  • 756
  • 9
  • 12
9

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?

Community
  • 1
  • 1
Han
  • 3,052
  • 2
  • 22
  • 31
2

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))
}
Saren Inden
  • 3,450
  • 4
  • 32
  • 45
0

If you are willing to give up precision you can use a Double to roughly calculate factorials up to 170:

func factorial(_ n: Int) -> Double {
    if n == 0 {
        return 1
    }
    var a: Double = 1
    for i in 1...n {
        a *= Double(i)
    }
    return a
}

If not, use a big integer library.

0

First we need to declare temp variable of type double so it can hold size of number.
Then we create a function that takes a parameter of type double.
Then we check, if the number equal 0 we can return or do nothing. We have an if condition so we can break the recursion of the function. Finally we return temp, which holds the factorial of given number.

var temp:Double = 1.0

func factorial(x:Double) -> Double{
    if(x==0){
        //do nothing
    }else{
        factorial(x: x-1)
        temp *= x
    }
    return temp
}

factorial(x: 21.0)
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • Please find the punctuation on your keyboard. Note that you can [edit] your post if you need to improve something. And this might help: https://stackoverflow.com/editing-help – Yunnosch Mar 28 '22 at 16:42
  • Please double check my edits. If I got something wrong please take it as illustration of important punctuation is for understanding and feel free to fix what I broke unintentionally. – Yunnosch Mar 28 '22 at 16:47
  • thanks the answer seems better now @Yunnosch – eslam mohamed Apr 04 '22 at 13:03
0

This is an extension that returns the factorial value of an Int in swift. It maxes out at 170!, but hopefully it works for anyone's coding issues!

extension Int {
 var factorial:Double {
  var num:Double = Double(self)
  var product:Double = 1
   while(num > 0) {
    product *= num
    num -= 1
   }
  return product
 }
}

print(170.factorial) // 7.257415615308004e+306
print(21.factorial) // 5.109094217170944e+19
-1

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)
}
Peter Schorn
  • 916
  • 3
  • 10
  • 20
  • 1
    The question is asking how to calculate 21!. This answer fails for all integer types since 21! is too large for all built-in integer types. – HangarRash Mar 05 '23 at 05:56
-1

I make function calculate factorial like this:

func factorialNumber( namber : Int ) -> Int {
    var x = 1
     
    for i in 1...namber {
        x *= i   
    }
    return x 
            
}
print ( factorialNumber (namber : 5 ))
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
wasim
  • 7
  • 2
-2

Using recursion to solve this problem:

    func factorial(_ n: UInt) -> UInt {
        return n < 2 ? 1 : n*factorial(n - 1)
    }
Hunter 19
  • 19
  • 1
-2
func factorial(a: Int) -> Int {

    return a == 1 ? a : a * factorial(a: a - 1)
}

print(factorial(a : 5))

print(factorial(a: 9))
4b0
  • 21,981
  • 30
  • 95
  • 142