ActiveState Code

Recipe 67668: Factorial


One Liner Factorial function This code gets factorial of a number and for negative numbers returns 1

Python
1
2
3
4
5
6
#calculates factorial and for n <=1 n! = 1
fac = lambda n:n-1 + abs(n-1)and fac(n-1)*n or 1L
#another version
fac = lambda n:[1,0][n>0] or fac(n-1)*n
#and another
fac = lambda n:reduce(lambda a,b:a*(b+1),range(n),1)

Discussion

The recursive implementation of factorial is easy but using lambda keyword of python it becomes a bit tough as we can't use conditional if else in lambda. If a user wants to return a factorial function on the fly using lambda than this may be the solution

Comments

  1. 1. At 7:01 a.m. on 26 oct 2001, Patrick O'Brien said:

    Larger Factorials. This function can be improved to handle larger factorials by changing the code to use long integers:

    f = lambda n:n-1 + abs(n-1) and f(n-1)*long(n) or 1
    
  2. 2. At 7:30 a.m. on 27 dec 2001, panoplos cechnokiv said:

    No need for the complexity... Just do the following:

    f = lambda n: n and f(n-1)*long(n) or 1

  3. 3. At 7:35 a.m. on 27 dec 2001, panoplos cechnokiv said:

    Ignore this... This doesn't handle negative values. =)

    -- gently inserting foot into mouth...

  4. 4. At 3:48 a.m. on 8 apr 2002, Chema Cortes said:

    functional solution. I want to point that the third formula is a functional solution (non recursive). A more concise formula:

    fac=lambda n: [1,0][n>0] or reduce(lambda x,y: x*y, xrange(1,n+1))
    
  5. 5. At 3:54 a.m. on 8 apr 2002, Chema Cortes said:

    functional solution. Or better:

    f=lambda n: n&lt;=0 or reduce(lambda a,b: a*b,xrange(1,n+1))
    
  6. 6. At 10:16 a.m. on 24 jun 2002, Carl Bray said:

    Requires long conversions. Trying to get the factorial of 20 causes an overflow.

    lambda n: n&lt;=0 or reduce(lambda a,b: a*b,xrange(1,n+1))
    OverflowError: integer multiplication
    
    I've amended the function to handle this.
    
    lambda n: n&lt;=0 or reduce(lambda a,b: long(a)*long(b),xrange(1,n+1))
    
  7. 7. At 1:28 p.m. on 8 jul 2005, Frank P Mora said:

    A one-line numeric function using list comprehensions.

    >>> f= lambda n: [[[j for j in (j*i,)][0] for i in range(2,n+1)][-1] for j in (1,)][0]
    >>> f(5)
    120
    
    If I were going to use reduce which might be removed from python I would
    use it with the operator mul. Long ints are automatic in Python 2.4.
    
    >>> from operator import mul
    >>> f= lambda n: reduce(mul,range(2,n+1))
    >>> f(6)
    720
    
    Assuming no one would want or need the factorial of anything less than 2.
    
  8. 8. At 7:27 a.m. on 20 jul 2005, Frank P Mora said:

    A better list comprehension expression. Steven Bethard pointed out in recipe 436482 that

    f= lambda n: [j for j in [1] for i in range(2,n+1) for j in [j*i]] [-1]
    
    is equivalent but easier to read, write and use.
    
  9. 9. At 8:07 a.m. on 4 oct 2007, Simone Leo said:

    just add initial value... ... And it also handles 0 and 1.

    reduce(operator.mul, xrange(2,n+1), 1)
    

Sign in to comment