Factorial function - design and test.

Posted by lukas on Stack Overflow See other posts from Stack Overflow or by lukas
Published on 2011-02-20T06:17:17Z Indexed on 2011/02/20 7:25 UTC
Read the original article Hit count: 216

I'm trying to nail down some interview questions, so I stared with a simple one.

Design the factorial function.

This function is a leaf (no dependencies - easly testable), so I made it static inside the helper class.

public static class MathHelper
{
    public static int Factorial(int n)
    {
        Debug.Assert(n >= 0);
        if (n < 0)
        {
            throw new ArgumentException("n cannot be lower that 0");
        }

        Debug.Assert(n <= 12);
        if (n > 12)
        {
            throw new OverflowException("Overflow occurs above 12 factorial");
        }

        //by definition
        if (n == 0)
        {
            return 1;
        }

        int factorialOfN = 1;
        for (int i = 1; i <= n; ++i)
        {
            //checked
            //{
                factorialOfN *= i;   
            //}
        }
        return factorialOfN;
    }
}

Testing:

    [TestMethod]
    [ExpectedException(typeof(OverflowException))]
    public void Overflow()
    {
      int temp = FactorialHelper.MathHelper.Factorial(40);
    }

    [TestMethod]
    public void ZeroTest()
    {
        int factorialOfZero = FactorialHelper.MathHelper.Factorial(0);
        Assert.AreEqual(1, factorialOfZero);
    }

    [TestMethod]
    public void FactorialOf5()
    {
       int factOf5 = FactorialHelper.MathHelper.Factorial(5);
       Assert.AreEqual(120,factOf5);
    }

    [TestMethod]
    [ExpectedException(typeof(ArgumentException))]
    public void NegativeTest()
    {
        int factOfMinus5 = FactorialHelper.MathHelper.Factorial(-5);
    }

I have a few questions:

  1. Is it correct? (I hope so ;) )
  2. Does it throw right exceptions?
  3. Should I use checked context or this trick ( n > 12 ) is ok?
  4. Is it better to use uint istead of checking for negative values?
  5. Future improving: Overload for long, decimal, BigInteger or maybe generic method?

Thank you

© Stack Overflow or respective owner

Related posts about c#

Related posts about unit-testing