Back to DFS's Workshop Page
Back to Agenda Page


Recursive Factorial

Quick Links

Given that one PHP script can call another, logically, it would follow that a PHP script could call itself. This capability has many possible uses, including editing a file or navigating a directory tree. These require user intervention to activate the next stage. Here, however, we will look at a situation where the script automatically calls itself until a task is completed.

This page presents a classic example of recursion, the calculation of a factorial.

For recursion to work, it must be started and then stopped at the appropriate time. Here, we will use an HTML page to allow the user to start the process by entering a number.When the submit button is clicked, a PHP script is activated which does one multiplication and then calls itself. This is done repeatedly until the number one is the final multiplier.

To see how this could work, try this possible implementation. Try entering a 5 and then watch the URL to see the values that are passed.

The HTML Script

The HTML starter script is here a simple one with a form that gets a single value, the factorial number passed as fn.

<p>Enter the number which you wish to calculate the factorial of. Then click on "Factorial!"</p>

<form method=GET action=factorial.php>
<table border>
<tr>
 <td>Factorial Number</td><td><input type="text" name="fn" value="" size="5"></td>
</tr>
<tr>
<td colspan="2" align=center>
  <input type="submit" value="Factorial!"><input type="reset">
</td>
</tr>
</table>
</form>

The Recursive PHP Script

This script is called by factorial.html and will call itself repeatedly until the final multiplier is used.

The beginning of the script handles the incoming data. Besides the factorial number $fn, e.g., the 5 of 5!, which we need to print out after the final execution of the script, we must also deal with the intermediate multiplier $fm and the intermediate/final product $factorial. The intermediate multiplier must be decremented with each call of the script, while the intermediate product must be kept track of.

The first value that the script needs to check is the factorial number provided by the user.

$fn = $_REQUEST['fn'];
if( empty($fn) )
   die("<H1>The value of 0! is 1.</H1>\n");
if( !ctype_digit($fn) )
   die("<H1>The string $fn contains one or more non-digit characters.</H1>\n");
After the value of the factorial number is copied to the local variable $fn, this code first checks to see if the user clicked on the submit button without typing anything into the form. The script is exited if the variable is empty.

Next all of the characters in $fn are checked to ensure that they are base-ten digits. If anything else, such as a negative sign or alphabetic character, is found, the script is exited.

$fm = $_REQUEST['fm'];
$factorial = $_REQUEST['factorial'];
Next both of the other variables are set using the data passed from previous executions of this script, if in fact data was passed.
if( empty($factorial) )
{
   $factorial = 1;
   $fm = $fn;
}
If $factorial contains no value, it means that the script has been called by the HTML form, not by itself. The variable is set to 1 so later multiplication can be used to alter its value. Also, $fm is set to the factorial number entered by the user and will be decremented during each execution of the script.
$factorial *= $fm--;
After starting to output the HTML code with <html><head>, the new value of $factorial is calculated and $fm is decremented.

Next comes the code which facilitates the recursion.

if($fm > 0)
   echo "<meta http-equiv=\"refresh\" content=\"2 url=factorial.php?fn=$fn&fm=$fm&factorial=$factorial\">\n";
If $fm is greater than 0, this meta tag, after a two-second delay, causes factorial.php to be called again with the new values for $fn, $fm and $factorial being passed. If $fm has been decremented to zero, the final value for $factorial has been determined and no further recursion is necessary.
<?php
if( $fm > 0 )
{
   echo "<P>The intermediate value of $fn! is $factorial after multiplying by " . ($fm + 1) . ".\n";
}
else
   echo "<P>The value of $fn! is $factorial.\n";
?>
This code prints out information about the current status of the recursion, either an intermediate value or the final one.

The Complete Code

Save the following code as file factorial.html.

<!-- factorial.html - calls factorial.php, passing fn-->
<html>
<head>
<title>Factorials by Recursion</title>
</head>
<body>
<p><a HREF=../../recursivefactorial.html>Factorials by Recursion Page</a></p>
<hr>
<h1 align="center">Factorials by Recursion</h1>
<p>Enter the number which you wish to calculate the factorial of. Then click on "Factorial!"</p>

<form method=GET action=factorial.php>
<table border>
<tr>
 <td>Factorial Number</td><td><input type="text" name="fn" value="" size="5"></td>
</tr>
<tr>
<td colspan="2" align=center>
  <input type="submit" value="Factorial!"><input type="reset">
</td>
</tr>
</table>
</form>
<hr>
&copy; 2005 DFStermole<br>
Created 27 Nov 05<br>
Last Modified 28 Nov 05
</body>
</html>

Save the following code as file factorial.php.

<?php
// factorial.php - called by factorial.html, then calls itself
//     passing fn (factorial requested),
//             fm (intermediate multiplier), and (intermediate) factorial value
$fn = $_REQUEST['fn'];
if( empty($fn) )
   die("<H1>The value of 0! is 1.</H1>\n");
if( !ctype_digit($fn) )
   die("<H1>The string $fn contains one or more non-digit characters.</H1>\n");
$fm = $_REQUEST['fm'];
$factorial = $_REQUEST['factorial'];
if( empty($factorial) )
{
   $factorial = 1;
   $fm = $fn;
}
?>
<html>
<head>
<?php
$factorial *= $fm--;
if($fm > 0)
   echo "<meta http-equiv=\"refresh\" content=\"2 url=factorial.php?fn=$fn&fm=$fm&factorial=$factorial\">\n";
?>
<title>Factorial by Recursion</title>
</head>
<body>
<table border=0 width=100%><tr><td align=left><a HREF=../../recursivefactorial.html>Recursive Factorial Page</a></td><TD align=right><a HREF=factorial.html>Restart this script</a></td></tr></table>
<hr>
<h1 align="center">Factorial by Recursion</h1>
<?php
if( $fm > 0 )
{
   echo "<P>The intermediate value of $fn! is $factorial after multiplying by " . ($fm + 1) . ".\n";
}
else
   echo "<P>The value of $fn! is $factorial.\n";
?>
<hr>
&copy; 2005 DFStermole<br>
Created 27 Nov 05<br>
Last Modified 29 Nov 05
</body>
</html>

Notes


© 2005 DFStermole
Created: 27 Nov 05
Last Modified: 29 Nov 05