Factorial Fun
There are many computer programming languages and many more being developed all the time. Usually the first program when learning a new language is "Hello World!", which outputs the text "Hello World!" to the screen.For engineers, scientist and mathematicians the next program should be the factorial. The factorial is symbolized with an exclamation point, !, after a positive integer. It occurs often in probability and series. The factorial is the product of all integers from one up to and including the number.
- 1! = 1
- 2! = 1*2 = 2
- 3! = 1*2*3 = 6
- 4! = 1*2*3*4 = 24
- 5! = 1*2*3*4*5 = 120
The following example programs in various computer languages take a number from the user, without checking if it is valid, to keep the code simple, and returns its factorial. Each example includes an introduction and detailed description.
FORTRAN
FORTRAN is short for formula translation and it was the first successful computer language. It allowed people to use something similar to standard mathematical formulas to program a computer for performing a calculation. FORTRAN is still used extensively for computing, because there are many numerical libraries, it is easy to learn, and very efficient at number crunching. FORTRAN was standardized by ANSI and later ISO/IEC. FORTRAN 66 and FORTRAN 77 standards were similar, however, Fortran 90, Fortran 95 and on dropped some notation and added new features. The major change was that FORTRAN 77 was fixed format based on Hollerith punched cards that had 80 columns while later versions became free form. FORTRAN compilers are still supposed to accept FORTRAN 77 input files. In FORTRAN 77 columns 1-5 are identifier numbers, column 6 is a marker for continuation of the previous line, columns 7-72 are for the program statements and columns 73-80 are for identification information. Also, a C in column 1 marks a comment line that is ignored by the compiler. The final identification columns were very useful if the stack of cards was dropped. FORTRAN also ignores the case so that 'FACTORIAL', 'factorial' and 'Factorial' are the same thing to the compiler.FORTRAN 77
1: PROGRAM FACTORIAL
2:C A program to compute the factorial of a number.
3:C23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
4: INTEGER*8 K
5:C INTEGER*4 N -- Optional statement
6: 20 CONTINUE
7: WRITE(6,300)
8: READ * , N
9: IF ( N .LT. 1 ) STOP
10: K=1
11: DO 10 I=1,N
12: K = K*I
13: 10 CONTINUE
14: WRITE(*,*) N,'! = ',K
15: GOTO 20
16: 300 FORMAT("Enter a number > 0, or 0
17: &to quit")
18: END
Note: the line numbers are not part of the code and should be removed to compile the code.Line Descriptions:
- The PROGRAM statement is where the code starts. There must be exactly one PROGRAM statement for any code.
- A Comment line ignored by the compiler but tells what the program does.
- A comment line I use to track what columns I am using
- Define K to be a double precision ( 8 Bytes) number
- A comment line ignored by the compiler, by default variables with names begining with i,j,k,l,m or n are single precision integers number
- The statement number is and address where the code may go to later. The CONTINUE statement does not do anything but indicates to go on to the next statement
- A WRITE statement indicates to write or output to file pointer 6, which is the standard output, using format 300
- READ from standard input a number, N. The read is list directed which means the read format is determined from the comma separated list of variables to read
- If N is less than 1 stop the program
- Set K equal to one, Otherwise K would start as some random number.
- DO begins a loop that ends at marker 10. A loop is where the section of code between the DO and the '10 CONTINUE' is repeated. The loop variable I starts at 1 and increases by 1 each loop until it reaches K. 'I' will be N for the last time that the loop is repeated.
- The variable K is set to K times I. Each time through the loop K is multiplied by a larger I value.
- Marks the end of the loop 10
- A List directed write statement which will write (output) according to the type of variable in the comma separated list. Note the text between the quotation marks is output as text. The first star indicates to write to standard output or unit 6.
- GOTO sends the program to the statement labeled 20. Note that the statement number does not need to be in order which makes things confusing and GOTO statements are discouraged.
- The format for the write on line 5. In this case only instructions are output as text.
- The & in column 6 indicates that this is a continuation of the previous line with a space in column 72 after "to"
- The end of the program. Only one end statement should be in a program file and a STOP is assumed before the end in FORTRAN 77. A STOP quits the program and an END marks the end of the program source code.
Save the code as fact.f
Compile the code. "gfortran fact.f"
Run the code " ./a.out"
Enter the following numbers 1,2,3,4,5,10,12,13,14,19,20,21,22,64,65,66,100,one
Comment out line 4 by putting a C in column 1 and recompile
Enter the following numbers 1,2,3,4,5,10,12,13,14,32,33,34,100,one
Fortran 95
In Fortran 90+ the column does not matter. Indentation is to help make the code readable. At this level there is not much difference between Fortran 90 series and FORTRAN 77 series. 1:PROGRAM FACTORIAL
2: ! Program to compute the factorial of a number
3: INTEGER (KIND=8) K
4: DO
5: WRITE( *,'(A)',ADVANCE='NO') 'Enter a number > 0 or 0 to quit :'
6: READ *, N
7: IF ( N < 1 ) EXIT
8: K=1
9: DO I=1,N
10: K = K*I
11: END DO
12: WRITE(UNIT=*,FMT="(I6,'! = ',I20)") N,K
13: END DO
14:END
Line Description
- Still only one Program statement per program. The main entry point and starting place of the program.
- Comments start with an exclamation point. It can start anywhere on a line and continues to the end of the line
- Named parameters now modify the variable definition. Kind=8 sets the variable kind to 8 which is an 8 byte length
- A 'DO' without anything else starts an infinite loop. The loop repeats from a matching 'END DO'. The 'DO' and 'END DO' can have names that must match.
- Write to unit * (standard output) with format 'A' ( Text of any length ) and parameter ADVANCE set to no. With Advance='NO' the program will not go to the next line, but will stay at the end of the line.
- List directed read from unit * (standard input) the value for N
- Test N and exit the DO if it is less than 1.
- Iniitialize K to 1. If not initialized K would be some random number
- Start of the loop with index 'I' increasing from 1 up to and including N
- Set 'K' to be 'K' times 'I', The value of K will be changed.
- The end of the loop with index 'I'
- Write to standard output with format of a 6 digit integer (I6) then the text '! = ', then a 20 digit integer
- The end of the do loop without an index, The code will return to the start of the DO
- The END of the program.
Save the code as fact.f95
Compile the code. "gfortran fact.f95"
Run the code " ./a.out"
Enter the following numbers 1,2,3,4,5,10,19,20,21,22,64,65,66,100
Comment out line 3 by putting an exclamation mark before INTEGER and recompile
Enter the following numbers 1,2,3,4,5,10,12,13,14,32,33,34,100
C Family
The 'C' family of programming languages, C,Objective C, Java, C++ have a similar syntax and appearance. They all use curly braces , {}, to group sets of commands. Parenthesis, (), are used for argument (or parameter) list where argument list are passed on to functions. Square brackets, [], are array indecies. Note that in C++ the parenthesis and square brackets can have there meaning changed though overloading. These languages are case sensitive so that 'main', 'Main' and 'MAIN' are three different functions.C
'C' is a minimal language with almost limitless capability, but few safeguards or programming aids. 'C' is available on almost all computing devices from embedded processors in toys to Supercomputers. It is easy to make mistakes in 'C'. The programmer must be very precise and complete for effective programming. This language is also very well defined. Check out http://www.ioccc.org/ for unique 'C' code examples that are very hard to read. 1:#include <stdio.h>
2:/* Program for computing the factorial of a number */
3:int main(int nvar, char** vars) {
4: int n,i;
5: long long int k;
6: while( 1 ) {
7: printf("Enter a number > 0, or 0 to quit :");
8: scanf("%d\n",&n);
9: if( n < 1 ) break;
10: for(i=1,k=1;i<=n;i++) {
11: k *= i;
12: }
13: printf("%d! = %Ld\n",n,k);
14: }
15:}
Line Descriptions
- Includes the file stdio.h in this file before it is compiled. stdio.h is the standard input/output header file. It contains declarations for input and output functions used later. Header files are usually located in the directory /usr/include, /usr/share/include or some other system location.
- A comment begins with '/*' and ends with '*/'. The compiler ignores everything (except a '/*' - why?) between the symbols. It can include multiple lines.
- This is the start point of all 'C' programs. The first int indicates that the program will return an integer to the shell. The arguments nvar and vars pass command line values to the program. An optional main statement could be 'void main() {' which would ignore command line arguments.
- Declares variables n and i to be integers. An integer has a size that is efficient for the hardware, usually 4 bytes. All variables in C must be declared, that is have there types defined.
- Declares variable k to be at least 8 bytes.
- A 'while' will repeat its statement as long as its argument is true. In 'C' a number other than 0 is true. This statement will repeat the code between curly braces forever. Because 1 is always considered true.
- This will output the text. By default it ends on the same line.
- Read from standard input a decimal number and put it in the memory location of n. In 'C' all arguments are passed as a copy of the value, so we gave the scanf function a copy of the memory location of 'n' rather than a copy of n. scanf can then change the value at the memory location effectively changing n.
- If n is less than 1 leave (break out of) the loop. This will send the code to line 15 which will then end the program. Alternatives to the break could be a 'return' or 'exit'.
- The beginning of the factorial loop. The 'for' statement has three parts inside the parenthesis separated by semicolons, ;, The first is an initialization where we set i=1 and k=1. The next is an exit test performed at the start of the loop. If this test is false the control will go past the end of the loop. The third part updates index values. 'i++' indicates to add 1 to 'i' at the end of the loop.
- This will replace the value of k with the current value of k times the value of i. The *= shortens the statement from 'k = k * i'.
- This curly brace ends the factorial calculation loop. The code goes back to line 10.
- Write the result to standard output with a format. In the format %d indicates to write n as a decimal number and %Ld indicates to write k as a long long decimal number. The %Ld format may not work on all compilers.
- This curly brace ends the while loop. The code goes back to line 6.
- This curly brace ends the main function and hence the program.
Save the code as fact.c
Compile the code. "gcc fact.c"
Run the code " ./a.out"
Enter the following numbers 1,2,3,4,5,10,19,20,21,22,64,65,66,100
Remove both longs from line 5 and recompile
Enter the following numbers 1,2,3,4,5,10,12,13,14,32,33,34,100
Put the longs back and remove the L from the printf in line 13 and recompile
Enter the following numbers 1,2,3,4,5,10,12,13,14,32,33,34,100
C++
C++ stands for C plus class. Classes are an object oriented programming construct that is very useful for separating code into lots of parts. Object oriented programming is good for graphical interfaces and data centric operations. For our simple program there is not much difference but in another post including a graphical interface the code will change significantly. The main difference in is the input and output statements. 1:#include <iostream>
2:// Program for computing the factorial of a number
3:int main(int nvar, char** vars) {
4: int n,i;
5: long long int k;
6: while( 1 ) {
7: std::cout << "Enter a number > 0, or 0 to quit :";
8: std::cin >> n;
9: if( n < 1 ) break;
10: for(i=1,k=1;i<=n;i++) {
11: k *= i;
12: }
13: std::cout << n << "! = " << k << std::endl;
14: }
15:}
Line Descriptions
- Includes the iostream header for input and output
- A one line comment starts with '//' and runs to the end of the line.
- The main entry point - see C code line 3
- Declarations for n and i
- Declaration for k
- Begin main loop
- std:: is an indicator that the next item is in namespace std. This is meant to avoid conflicts where an item may have naming conflicts. We could have named a variable cout which would be different than the cout in the std namespace. This namespace practice helps to isolate local variables from system or library variables.
cout is an output stream connected to standard output.
'<<' sends the next item to the output stream. How it is sent depends on the item and other formatting information set on the stream. Note that '<<' is the left shift operator by default.
By default the stream stays at the last operation. - cin is an input stream connected to standard input.
'>>' sends data to the next item. A pointer to the memory location is not needed. Note that '>>' is the right shift operator by default. - Exit condition test.
- Loop for calculating the factorial
- k = k * i
- end of factorial loop
- Sends the value of n, then the string "! = ", then value of k and finally a new line or carriage return to standard output.
- end of the main loop.
- end of the main function and the program.
Save the code as fact.cpp
Compile the code. "g++ fact.cpp"
Run the code " ./a.out"
Compare what happens in the C++ code with what happens in the C code when you enter "Five". Hint: For console programs a [Ctrl]C will stop a running program.
Java
Java was written to remove many problems in programming C++ by eliminating some features and maintaining stricter object orientation. Java does not have direct access to pointers and has automatic garbage collection. One of the major difficulties in C and C++ is memory leaks. A memory leak is where the program allocates ( or reserves ) memory for a variable but does not properly deallocate (or free) the memory when it is done with the variable. Another problem is when the memory is deallocated before being done with the variable. Garbage collection is where the system keeps track of when the variable is no longer needed and will free the memory automatically. Java also checks array bounds which is a problem often causing segmentation faults in other languages.
Java is partially an interpreted language, that is the code runs one command at a time. Running java code involves two steps, first the code is compiled into "bytecode" with javac, then the bytecode, in a .class file, is run by an interpreter, "java". The interpreter is specific for each platform while the bytecode is independent of the computer platform. The interpreter is probably written in C for each platform. Java is a slow language and uses a lot of memory but it will run on most platforms. Java also has strong security mechanisms so that it is relatively safe to run programs downloaded from the internet, If you do not allow the program extra privileges.
1:import java.io.*;
2:class Fact {
3: /** Program to compute the factorial of a number*/
4: public static void main(String[] args) {
5: int i,n;
6: long k;
7: String nstr;
8: try{
9: InputStreamReader cin = new InputStreamReader(System.in);
10: BufferedReader br = new BufferedReader(cin);
11: while(true) {
12: System.out.print("Enter a number > 0, or 0 to quit :");
13: nstr = br.readLine();
14: n = Integer.parseInt(nstr);
15: if( n < 1) break;
16: k = 1;
17: for( i=1; i<=n; i++) {
18: k *= i;
19: } // for( i
20: System.out.println(n+"! = "+k); // Display the result.
21: } // while(true)
22: } catch( IOException ioe) {
23: System.out.println(ioe);
24: } finally {
25: System.out.println("Leaving now!!");
26: } // try
27: } // main
28:} // class Fact
Line Descriptions
- The import makes classes available to this program. The star '*' is short for all so this import makes all of the classes in java/io available for this program.
- Defines a class named Fact. The file name should be the same as the main class with a ".java" appended.
- A comment. Comments in java can be multi-line starting with '/*' and ending with '*/' or to the end of the line starting with //. The special three character start of a comment /** makes the comment appear in the documentation generated with javadoc or Doxygen.
- This is the program starting main entry point. In Java there can a main function in each class. This is very handy because the main function can be a test function so each class can be executed by itself. The qualifiers before main are : public - The function or data are available to all other classes in the code. static - Indicates this is part of the class and there is only one. When a class is instantiated (created) this is not copied. Also, the class does not need to be instantiated to use this function or data.
- Declares i and n to be of type int, Numbers in Java are defined to be specific sizes so that an 'int' is always 4 Bytes instead of an efficient size for the hardware.
- Declares k to be of type 'long' which is an eight byte integer.
- The java io system reads only bytes, characters or Strings. So the program needs a String object.
- Error handling is enforced in Java. The io methods may throw an exception (error) so our program must define a section of code we will try to run and if it fails we will catch the exception (error) and possibly do something to fix the problem.
- The program needs a reader which can take data from a stream and convert it to characters. System.in is the standard input InputStream. An InputStream can only read bytes of data.
- A BufferedReader can read a line of input as a String object. This one is connected to the InputStreamReader created in line 9. So now the BufferedReader sequence is System.in -[bytes]-> cin -[characters]-> br -[String]->.
- Begin the outer loop that ends on line 21
- Write the prompt to standard output (System.out)
- Read a line from the BufferedReader br.
- Convert the String nstr to an decimal integer by parsing it.
- Test if the user wants to leave the loop and hence the program
- initialize the value of k to 1. The compiler will force the programmer to initialize all variables.
- The loop to compute the factorial with i starting at 1 and increasing by 1 each loop until it is not less than or equal to n.
- Reset k to be equal to k times i
- end of the factorial for loop. I have added a comment (//) to mark what this curly brace is closing.
- Write the result. println will write a String to the stream. A String '+' a number will convert the number to a String and add it to the String. Therefore, n+"! = "+k, is a String.
- End of the main loop with a comment to indicate what is ended
- A catch will run a section of code if an Exception of the type in the catch is thrown in the matching try block. In other words, if there was a problem in the input/output (IOException) run the following code block .
- Write a statement to standard output about what was the problem.
- A finally will be ran at the end of the matching try block whether or not an exception happened.
- Write that the code is done to standard output.
- End of the try/catch/finally code.
- End of the main function with a comment
- End of the class Fact with an optional comment.
Save the code as Fact.java
Compile the code "javac Fact.java"
Run the code "java Fact"
Test various numbers as above.
Java has a class for arbitrary precision integers called BigInteger. The following code uses this class instead of a built-in long integer type for k.
import java.io.*;
import java.math.BigInteger;
class BigFact {
/** Class to compute the factorial of a number to arbitrary precision*/
public static void main(String[] args) {
int i,n;
BigInteger k;
String nstr;
try{
InputStreamReader cin = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(cin);
while(true) {
System.out.print("Enter a number > 0 or 0 to quit :");
nstr = br.readLine();
n = Integer.parseInt(nstr);
if( n < 1) break;
k = BigInteger.ONE;
for(i=1;i<=n;i++) {
k = k.multiply(BigInteger.valueOf(i));
}
System.out.println(n+"! = "+k.toString()); // Display the result.
} // while(true)
} catch( IOException ioe) {
System.out.println(ioe);
} finally {
System.out.println("Leaving now!!");
}
} // main
} // class BigFact
Save the code as BigFact.java
Compile the code "javac BigFact.java"
Run the code "java BigFact"
Test various numbers as above.
Note what is in the low order decimal places for 100! and see if this helps to explain the results of 64!, 65! and 66! above.
C Note
The C programming languages are rentrant, that is a method can call itself. This feature is often illustrated with a factorial computation program such as
#include <stdio.h>
/* Program for computing the factorial of a number */
long long int factorial(int i) {
if( i == 1) return 1;
return i*factorial(i-1);
}
int main(int nvar, char** vars) {
int n;
long long int k;
while( 1 ) {
printf("Enter a number > 0 or 0 to quit :");
scanf("%d",&n);
if( n < 1 ) break;
k = factorial(n);
printf("%d! = %Ld\n",n,k);
}
}
This is an inefficient way to compute factorial because each entry into the function 'factorial' has some extra overhead. In Java with larger numbers this could overflow the stack resulting in a program crash.
No comments:
Post a Comment