Search code examples
javapascals-triangle

Pascal's triangle pattern suddenly breaks


The following program prints Pascal's triangle. The program works fine for small input but if you pass the constructor a value greater than 13, the pattern breaks. I don't understand why and need help. Also comment on my coding style:

/** Following program prints the Pascal triangle 
 * 
 * read from bottom to top to understand the implementation
 */
public class PascalTriangle {

    int noOfRows;

    PascalTriangle(int noOfRows)                    /// user have to provide how many lines of Pascal's triangle he wants to print
    {
        this.noOfRows = noOfRows;
    }
    private int factorial(int n)                    /// this method calculate factorial which we use to calculate the NCR
    {  
        int fact = 1;
        for(int i = 2 ; i <= n ; ++i)
            fact*=i;
        return fact;
    }
    private void printSpaces(int spaceCount)        /// this method prints spaces before the first elements of every line
    {
        for(int i = 1 ; i < spaceCount ; ++i)  
            System.out.print("   ");
    }
    private void printElement(int n , int r)                                /// this method prints an element
    {   
        System.out.printf("%3d",factorial(n)/(factorial(n - r) * factorial(r)));  /// calculate NCR for given no of row and given r
        System.out.print("   ");                                             /// print two spaces after every element
    }
    private void printRow(int rowNumber)           /// this method prints elements of a row
    {  
        int r = 0;                                 /// to calculate NCR r = 0 is always zero for first element of a row
        int noOfElements = rowNumber + 1;          /// Each row contains one element more than which row it is 
        for(int i = 1 ; i <= noOfElements ; ++i)   /// run this loop until you print all elements of that row
        {
        printElement(rowNumber , r);               /// call the printElement method and tell it for which row is it going to print the element and what is r for that element
        ++r;                                       /// increase r for every element;
        }
    }
    public void printPascalTriangle()       /// this function prints the Pascal's Triangle
    {
        int rowNumber = 0;                  /// this variable decides which row of the Pascal's Triangle should print 
        int spaceCount = noOfRows;
        while(rowNumber < noOfRows)         /// print rows of Pascal's  triangle until all rows are printed
        {  
            printSpaces(spaceCount);        /// before printing any row print desired number of spaces 
            printRow(rowNumber);            /// this method prints a row and its argument decides which row to print 
            System.out.println();           /// after printing every row go to next line for next row
            rowNumber++;                    /// increase the row number because next time i want to print next row
            spaceCount--;                   /// decrease space count because next line needs less spaces before first element
        }

    }
    public static void main(String[] args)
    {
        PascalTriangle triangle = new PascalTriangle(20);   /// create an object and provide how many lines you want to print
        triangle.printPascalTriangle();                     /// call the prinitPascalTrianle method to print your Pascal Trianle
    } 

}

Solution

  • The problem is in your fact() function. Let's separate it out and run it:

    public class PascalTriangle {
    
        private int factorial(int n)
        {
            int fact = 1;
    
            for (int i = 2; i <= n; i++)
            {
                fact *= i;
            }
    
            return fact;
        }
    
        public static void main(String[] args)
        {
            PascalTriangle triangle = new PascalTriangle();
    
            for (int i = 1; i < 20; i++)
            {
                System.out.printf("%d = %d\n", i, triangle.factorial(i));
            }
        }
    }
    

    You can see that once you get beyond fact(12) the answers are coming out wrong:

    > java PascalTriangle
    1 = 1
    2 = 2
    3 = 6
    4 = 24
    5 = 120
    6 = 720
    7 = 5040
    8 = 40320
    9 = 362880
    10 = 3628800
    11 = 39916800
    12 = 479001600
    13 = 1932053504
    14 = 1278945280
    15 = 2004310016
    16 = 2004189184
    17 = -288522240
    18 = -898433024
    19 = 109641728
    >
    

    Because factorial grows so fast you've exceeded the capacity of an int. If we take that same code and replace all the int declarations with long, you can see that we get further sans error:

    > java PascalTriangle
    1 = 1
    2 = 2
    3 = 6
    4 = 24
    5 = 120
    6 = 720
    7 = 5040
    8 = 40320
    9 = 362880
    10 = 3628800
    11 = 39916800
    12 = 479001600
    13 = 6227020800
    14 = 87178291200
    15 = 1307674368000
    16 = 20922789888000
    17 = 355687428096000
    18 = 6402373705728000
    19 = 121645100408832000
    > 
    

    This seems an expensive way to calculate Pascal's triangle when each row can be derived from the previous using addition.