how to code a factorial - java

my question is not so much about code as it is the logic behind writing a factorial program. I am currently taking a MOOC at the University of Helsinki and I have become stuck on this exercise. As the course moves on to new exercises the instructions have become more and more vague. I realize this probably isn't the place to ask this question and if you must tag it or remove it, I do understand. I am trying to learn this on my own as I do not have the time or money to actually attend a university. This course has no time constraint and I wont be receiving a certificate of achievement for it, I simply want the knowledge.
these are the instructions given for the exercise
Create a program that calculates the factorial of the number n. The factorial n! is calculated using the formula 1*2*3*...*n. For example 4! = 1*2*3*4 = 24. Additionally, it is defined that 0! = 1.
// i don't understand the example that 4!= 1*2*3*4 = 24
// or how 0! = 1 pertains to multiplying numbers in succession to find the
// factorial of the user input number.
// i understand that 0! = 1 simply delclares that 0 is not equal to 1
// and 4 is not equal to 24, however if the 4! = portion of this statement
// is in reference to the user input number 4 that statement would not be
// true as 1*2*3*4 does equal 24 and 4 would be the number of executions
// of the block execution of the loop required to write the factorial
// program.
// EDIT: okay so according to this http://en.wikipedia.org/wiki/Factorial
// i am wrong about what is being done here as they are not declaring
// that 4 not equals 24 but yet that 4! is a way of correlating the non
// negative numbers up to 4, but given that math is not my strong suit
// it is even more confusing to me as to what i should be doing.
Example outputs:
Type a number: 3
Factorial is 6
Type a number: 10
Factorial is 3628800
my current code attempt is as follows
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Type a number:");
int userIn = Integer.parseInt(reader.nextLine());
int factorial = 1;
int extra = 1;
int sum = 0;
while (factorial <= userIn) {
factorial++;
sum = factorial + userIn + extra;
}
System.out.println("The factorial is:"+sum);
}
}
I do not understand what it is that i am missing, i know from research that in the real world you would not code this as there are libraries you can download to perform the factorial function that are much more efficient than what i could code, but i don't want to simply skip this exercise with the knowledge that someone else has already coded and created a library to make our lives easier, i want to learn everything that this course has to offer. if i have made a simple error i don't mind an offered code correction, however i want to understand what makes the factorial operation tick so to speak, not just be given the answer so i can move on.

The factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. Eg:- 4!=1*2*3*4 . 0!=1 states that factorial of 0 is 1 and not that 0 is not equal to 1. The value of 0! is 1, according to the convention for an empty product. An empty product, or nullary product, is the result of multiplying no factors. It is by convention equal to the multiplicative identity 1 , just as the empty sum—the result of adding no numbers—is by convention zero (Like the sum of first 0 natural numbers would we 0), the additive identity.
For more on empty products read here http://en.wikipedia.org/wiki/Empty_product
For the programming part, there are basically two approaches to a factorial program:-
Using a for loop (No recursion)
int factorial ( int input )
{
int x, fact = 1;
for ( x = input; x > 1; x--) // iterating from n -> n-1 -> n-2 ... 1
{
fact *= x; // multiplying each number into the fact variable to get the factorial
}
return fact;
}
Recursive approach -The function calls itself ( Note- avoid using this approach in actual programming as it may be highly resource consuming and bug prone, As pointed out by "Edwin Buck" in the comments)
public int Factorial(int n)
{
if (n == 0)
{
return 1; //Base condition - If factorial reaches 0 return 1 and end recursion
}
else
{
return n * Factorial(n-1); // For factorial of n, function returns n * Factorial(n-1) i.e recursively calling the factorial function with one less value in the parameter untill 0 is reached (upon which base condtiion will be evaluated)
}
}

Try this one if you don't want to use an external function
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Type a number:");
int userIn = Integer.parseInt(reader.nextLine());
int factorial = 1;
int i= userin;
while (userin >= 1) {
factorial *= userIn;
userin--;
}
System.out.println("The factorial is:"+factorial);
}
}

The problem is here
sum = factorial + userIn + extra;
where you "calculate" your factorial from the latest factorial++ value in the loop.
You can't calculate factorials from sums in this manner. Factorials are products of all the integers between 1 and the "factorial" number, so
1! = 1
2! = 1 * 2
3! = 1 * 2 * 3
4! = 1 * 2 * 3 * 4
If you start off calculating your factorial wrong, then the other parts of the problem don't matter much, they will be wrong by extension.

// Factorial example (ie 5 * 4 * 3 * 2 * 1)
function factorial($n) {
if ($n == 1) return 1;
return $n * factorial($n-1);
}
echo factorial(5); // Outputs 120
// Nested Array Summing Example
$example = array(1, 2, array(10,20,30), 4);
function sum_array($array) {
$total = 0;
foreach ($array as $element) {
if(is_array($element)) {
$total += sum_array($element);
} else {
$total += $element;
}
}
return $total;
}
echo sum_array($example); // Outputs 67

Your question is similar to mine, and it was actually a school assignment.
Though question is answered, i will contribute my solution.
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int i = 1;
int factorial = 1;
System.out.println("Give number: ");
int number = Integer.parseInt(reader.nextLine());
while (i <= number) {
factorial = factorial * i;
i++;
}
System.out.println("Answer is " + factorial);
}

Related

Java beginner: Dividing input value in half using a loop but cannot use arrays, built-in sorting routines or any other Java Collections classes

Java Beginner: I have most of the code complete to solve the problem below but having trouble with my loop section since it is currently dividing one value. It should continue dividing until it reaches 1. I'm not sure what's wrong so any assistance is greatly appreciated!! However, I cannot use arrays, built-in sorting routines or any other Java Collections classes
Problem:
Write a program that will prompt the user for a positive integer: N. The program will repeatedly divide the input in half using a loop, discarding any fractional part, until it becomes 1. The program should print on separate lines:
the sequence of 'halved' values, one per line
the number of iterations required
the value of log2(N)
My code and output when entering a value of 9:
import stdlib.StdIn;
import stdlib.StdOut;
public class DS1hw1b {
public static void main(String[] args) {
int countIteration = 0;
StdOut.println("enter a positive number: ");
int N = StdIn.readInt();
for (int i = 1; i <= 1; i++) {
countIteration++;
if ((N/2) != 1)
StdOut.println(N/2);
StdOut.println("number of iterations: " + countIteration);
//compute log formula
StdOut.println("log2 of input: " + (Math.log(N)/Math.log(2)));
}
}
}
Output:
enter a positive number:
9
4
number of iterations: 1
log2 of input: 3.1699250014423126
However, I should see is 9, 4, 2, and 1 on separate lines and iteration of 3.
Your loop will only loop once - you initialize i with 1, which adheres to the condition i<=1, and stop adhering to it once i is incremented.
You're asked to divide N by 2 until it becomes 1 - this calls for a while loop:
int counter = 0;
while (n > 1) {
System.out.println(n);
counter++;
n /= 2;
}
System.out.println("Number of iterations: " + counter);
Per my comment to #Murelink. Here is the updated code but now the log2 formula shows as 0.0 for any number entered. I thought it would be best to show it this way. Anyway, I don't understand why it doesn't work since I didn't modify the formula. Thank you all for your help!
public static void main(String[] args) {
int countIteration = 0;
StdOut.println("enter a positive number: ");
int N = StdIn.readInt();
while (N > 1) {
N /= 2;
countIteration++;
StdOut.println(N);
}
StdOut.println("number of iterations: " + countIteration);
//compute log formula
StdOut.println("log2 of input: " + (Math.log(N)/Math.log(2)));
}
}

Divide by Zero Exception with Typecaste (Java)

import java.util.Scanner;
public class SumDigits {
public static void main(String[] args)
{
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
// prompt the user to enter a value and store it as the integer called number
System.out.print("Enter an integer: ");
double number = Math.abs(input.nextDouble());
System.out.println("The sum of the digits is " + sumNumbers(number));
input.close();
}
public static int sumNumbers (double number)
{
int sum = 0;
for (int i = 10, digit = 0; (number * 10) /i !=0; i *= 10, digit = (int)((number % i) - digit)/(i / 10))
{
sum += digit;
}
return sum;
}
}
At runtime, I get the error message
Exception in thread "main" java.lang.ArithmeticException: / by zero
referring to line 25 (my for loop conditions).
The loop worked fine until I tried type casting digit's value to an int, and I'm not really certain why that would cause any part of the loop to divide something by zero. I've gone over all the possibilities regarding the conditions that use rational expressions and can't deduce a contingency wherein any denominator would be set to zero. I get this error regardless of what number is input. I would not have chosen to save number as a double at all if it were not for the fact that my professor provided a number whose value exceeds that which can be stored within an int in one of his test cases. The program ran fine prior to the type cast and provided the correct answer for all other test cases.
Here you are doing
(number * 10) /i !=0
where number is double.
Floating point numbers aren't recommended for comparisons because of the way they get stored (in mantissa and exponent form). So, if this condition returns true, consider yourself lucky.
Because of that your loop is kinda never-ending loop. The reason you are getting arithmetic exception though is that here you are multiplying i by 10 in this kinda infinite loop. "i" reaches "integer" limit of 32 bits and overflows and ultimately makes all those 32 bits as 0.
Effectively, i=0 and both of the following throw divide by zero exception
(number * 10) /i
and
(number % i) - digit)/(i / 10)
The root cause of the ArithmeticException is the incorrect loop condition. Adding System.out.println("i=" + i + " i*10=" + (i * 10)); in the loop produces output:
i=10 i*10=100
i=100 i*10=1000
i=1000 i*10=10000
i=10000 i*10=100000
i=100000 i*10=1000000
i=1000000 i*10=10000000
i=10000000 i*10=100000000
i=100000000 i*10=1000000000
i=1000000000 i*10=1410065408
i=1410065408 i*10=1215752192
i=1215752192 i*10=-727379968
i=-727379968 i*10=1316134912
i=1316134912 i*10=276447232
i=276447232 i*10=-1530494976
i=-1530494976 i*10=1874919424
i=1874919424 i*10=1569325056
i=1569325056 i*10=-1486618624
i=-1486618624 i*10=-1981284352
i=-1981284352 i*10=1661992960
i=1661992960 i*10=-559939584
i=-559939584 i*10=-1304428544
i=-1304428544 i*10=-159383552
i=-159383552 i*10=-1593835520
i=-1593835520 i*10=1241513984
i=1241513984 i*10=-469762048
i=-469762048 i*10=-402653184
i=-402653184 i*10=268435456
i=268435456 i*10=-1610612736
i=-1610612736 i*10=1073741824
i=1073741824 i*10=-2147483648
i=-2147483648 i*10=0
First time control enters into loop the value of digit would be zero and not the last digit of entered number as you would have expected. Also you need to fix your loop termination condition as that is wrong. For example if number is 123 then at last expected iteration 1230/1000 = 1 and not 0 and loop does not end and rather leads to overflow. You can use the following:
public static int sumNumbers (double number)
{
int sum = 0;
for (int i = 10, digit = (int)(number % i); digit != 0; i *= 10, digit = (int)((number % i) - digit)/(i / 10))
{
sum += digit;
}
return sum;
}
This should work but I again recommend you to improve this code as this is not the ideal way.
Testing:
Enter an integer: 3456
The sum of the digits is 18

Checking whether a number is in Fibonacci Sequence?

It was asked to find a way to check whether a number is in the Fibonacci Sequence or not.
The constraints are
1≤T≤10^5
1≤N≤10^10
where the T is the number of test cases,
and N is the given number, the Fibonacci candidate to be tested.
I wrote it the following using the fact a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 0 ; i < n; i++){
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest =(5 * (cand *cand)) + 4;
int bTest = (5 * (cand *cand)) - 4;
int sqrt1 = (int)Math.sqrt(aTest);// Taking square root of aTest, taking into account only the integer part.
int sqrt2 = (int)Math.sqrt(bTest);// Taking square root of bTest, taking into account only the integer part.
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
But its not clearing all the test cases? What bug fixes I can do ?
A much simpler solution is based on the fact that there are only 49 Fibonacci numbers below 10^10.
Precompute them and store them in an array or hash table for existency checks.
The runtime complexity will be O(log N + T):
Set<Long> nums = new HashSet<>();
long a = 1, b = 2;
while (a <= 10000000000L) {
nums.add(a);
long c = a + b;
a = b;
b = c;
}
// then for each query, use nums.contains() to check for Fibonacci-ness
If you want to go down the perfect square route, you might want to use arbitrary-precision arithmetics:
// find ceil(sqrt(n)) in O(log n) steps
BigInteger ceilSqrt(BigInteger n) {
// use binary search to find smallest x with x^2 >= n
BigInteger lo = BigInteger.valueOf(1),
hi = BigInteger.valueOf(n);
while (lo.compareTo(hi) < 0) {
BigInteger mid = lo.add(hi).divide(2);
if (mid.multiply(mid).compareTo(x) >= 0)
hi = mid;
else
lo = mid.add(BigInteger.ONE);
}
return lo;
}
// checks if n is a perfect square
boolean isPerfectSquare(BigInteger n) {
BigInteger x = ceilSqrt(n);
return x.multiply(x).equals(n);
}
Your tests for perfect squares involve floating point calculations. That is liable to give you incorrect answers because floating point calculations typically give you inaccurate results. (Floating point is at best an approximate to Real numbers.)
In this case sqrt(n*n) might give you n - epsilon for some small epsilon and (int) sqrt(n*n) would then be n - 1 instead of the expected n.
Restructure your code so that the tests are performed using integer arithmetic. But note that N < 1010 means that N2 < 1020. That is bigger than a long ... so you will need to use ...
UPDATE
There is more to it than this. First, Math.sqrt(double) is guaranteed to give you a double result that is rounded to the closest double value to the true square root. So you might think we are in the clear (as it were).
But the problem is that N multiplied by N has up to 20 significant digits ... which is more than can be represented when you widen the number to a double in order to make the sqrt call. (A double has 15.95 decimal digits of precision, according to Wikipedia.)
On top of that, the code as written does this:
int cand = sc.nextInt();
int aTest = (5 * (cand * cand)) + 4;
For large values of cand, that is liable to overflow. And it will even overflow if you use long instead of int ... given that the cand values may be up to 10^10. (A long can represent numbers up to +9,223,372,036,854,775,807 ... which is less than 1020.) And then we have to multiply N2 by 5.
In summary, while the code should work for small candidates, for really large ones it could either break when you attempt to read the candidate (as an int) or it could give the wrong answer due to integer overflow (as a long).
Fixing this requires a significant rethink. (Or deeper analysis than I have done to show that the computational hazards don't result in an incorrect answer for any large N in the range of possible inputs.)
According to this link a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square so you can basically do this check.
Hope this helps :)
Use binary search and the Fibonacci Q-matrix for a O((log n)^2) solution per test case if you use exponentiation by squaring.
Your solution does not work because it involves rounding floating point square roots of large numbers (potentially large enough not to even fit in a long), which sometimes will not be exact.
The binary search will work like this: find Q^m: if the m-th Fibonacci number is larger than yours, set right = m, if it is equal return true, else set left = m + 1.
As it was correctly said, sqrt could be rounded down. So:
Even if you use long instead of int, it has 18 digits.
even if you use Math.round(), not simply (int) or (long). Notice, your function wouldn't work correctly even on small numbers because of that.
double have 14 digits, long has 18, so you can't work with squares, you need 20 digits.
BigInteger and BigDecimal have no sqrt() function.
So, you have three ways:
write your own sqrt for BigInteger.
check all numbers around the found unprecise double sqrt() for being a real sqrt. That means also working with numbers and their errors simultaneously. (it's horror!)
count all Fibonacci numbers under 10^10 and compare against them.
The last variant is by far the simplest one.
Looks like to me the for-loop doesn't make any sense ?
When you remove the for-loop for me the program works as advertised:
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest = 5 * cand *cand + 4;
int bTest = 5 * cand *cand - 4;
int sqrt1 = (int)Math.sqrt(aTest);
int sqrt2 = (int)Math.sqrt(bTest);
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
You only need to test for a given candidate, yes? What is the for loop accomplishing? Could the results of the loop be throwing your testing program off?
Also, there is a missing } in the code. It will not run as posted without adding another } at the end, after which it runs fine for the following input:
10 1 2 3 4 5 6 7 8 9 10
IsFibo
IsFibo
IsFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
Taking into account all the above suggestions I wrote the following which passed all test cases
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long[] fib = new long[52];
Set<Long> fibSet = new HashSet<>(52);
fib[0] = 0L;
fib[1] = 1L;
for(int i = 2; i < 52; i++){
fib[i] = fib[i-1] + fib[i - 2];
fibSet.add(fib[i]);
}
int n = sc.nextInt();
long cand;
for(int i = 0; i < n; i++){
cand = sc.nextLong();
if(cand < 0){System.out.println("IsNotFibo");continue;}
if(fibSet.contains(cand)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
I wanted to be on the safer side hence I choose 52 as the number of elements in the Fibonacci sequence under consideration.

How to print all palindromes upto 1000 without using any String,StringBuilder?

I have to write a code for printing all palindrome numbers up to 1000. Here is my code. I have dealt with 3 scenarios:
1-digit number
2-digit number
3-digit number
My third scenario is not printing just the palindromes but prints all the numbers. A hint will help me solve this.
public class PrintPalindrome {
public static void main(String args[])
{
Integer[] array=new Integer[1000];
for(int i=0;i<array.length;i++)
{
array[i]=i+1;
printPalindrome(array[i]);
//System.out.println(array[i]);
}
}
public static void printPalindrome(Integer a)
{
String num=Integer.toString(a);
int length=num.length()-1;
//System.out.println(num);
if(num.length()<=1)
{
System.out.println("" + num);
}
else if(num.length()==2)
{
if(num.charAt(0)==num.charAt(1))
System.out.println(num);
}
else if(num.length()>2)
{
//now deal with the numbers whose length is greater than 2
for(int i=0;i<=length;i++)
{
if(num.charAt(i)==num.charAt(length-i))
System.out.println(num);
}
}
}
}
Work out a solution with arithmetic…
This doesn't necessarily help with the code that you've already got, but it's approach to the problem in the title, How to print all palindromes upto 1000, which may be helpful to others who come across this question. It's often fun to try to solve these problems using the properties of the numbers, without worrying about converting them to strings. In this case, note that for any number n, you can get the leading digit by n % 10, that is, the remainder of n divided by 10, or n modulo 10. You can get the number whose digits are the same as the remaining digits of n as the integer quotient of n/10. E.g.,
1234 % 10 = 4
1234 / 10 = 123
Now, if you keep applying this deconstruction, you can get the individuals digits:
123 % 10 = 3
123 / 10 = 12
12 % 10 = 2
12 / 10 = 1
1 % 10 = 1
1 / 10 = 0
Now, if you take those numbers in the same order that you got them (4, 3, 2, 1), you can reconstruct the "reverse" number:
1 + 10(2 + 10(3 + 10(4 + 0))) = 4321
If we call this the reverse of a number, then number is a palindrome if and only if it's equal to it's reverse.
…and then translate it to Java
This is fairly straightforward to implement in Java, and it doesn't require any special casing about 1-digit numbers, 2-digit numbers, etc., or string manipulation. (As Kent points out in the comments, there's still a limit on how large the numbers that this handles is, but if you need to handle big numbers, you could (i) switch to a long; (ii) switch to a BigInteger.)
public class PalindromeExample {
/**
* Returns the number whose digits (base 10) are the reverse
* of number's (with no leading zeros).
* #param number the number to reverse
* #return the reversed number
*/
public static int reverse( int number ) {
int result = 0;
while ( number > 0 ) {
result = result * 10 + (number % 10);
number = number / 10;
}
return result;
}
/**
* Show the numbers less than 10000 whose digit sequences
* are palindromes.
*/
public static void main(String[] args) {
for ( int i = 0; i < 10000; i++ ) {
if ( i == reverse( i ) ) {
System.out.println( i );
}
}
}
}
0
1
2
3
…
9
11
22
…
99
101
111
…
151
161
…
8008
8118
…
9339
9449
9559
9669
9779
9889
9999
if(num.charAt(i)==num.charAt(length)-i)
is wrong. Even if you set parenthesis in the "right" place you still be wrong, because for example:
charAt(0) == charAt(3) //and what's char at 3?
if(num.charAt(i)==num.charAt(length-i-1))
should do the trick but then placing it in a for loop doesnt make any sense.
When a 3-digit number has 1st and 3rd digit the same it is actually a palindrome. Every other loop will just mess up your output.
For the requirement, we don't have to convert to string.
pls try if this works for you: (could be an one-liner)
for (int i = 1; i < 1000; i++)
if (i<10 ||(i<100&&i%11==0)||(i>100&&i%10==i/100) )
System.out.println(i);
Handling scenarios for each digit length to check if a number is a palindrome is not an appropriate approach.
Trying what the other answers suggest - like going through each and every number and checking if it is palindrome by reversing number digit by digit is better but even then it is not very efficient as it is brute force.
So, I would like to some suggestions if I may:-
Rather than going for brute force, any other approach if possible is preferable.
Even while resorting to brute force, using the library functions is
better and at least as efficient as any code we can write. ex - Integer.reverse() function for reversing an integer.
I have had a try at generating the palindromes(rather than trying one by one). This is not bug-proof yet as I have not tested extensively but should be able to convey the concept.
public class PrintPalin {
public static void main(String[] args) {
// TODO Auto-generated method stub
//The first palindrome = 1
int i = 1;
while(i<=10000){
System.out.println(i);
i = nextPalin(i);
}
}
static int nextPalin(int i){
StringBuilder sb = new StringBuilder(String.valueOf(i));
int len = sb.length(), right = len/2, left;
if(len%2!=0 || len == 1){
left = right;
}else{
left = right-1;
}
//System.out.println(left + " " + right);
while(right<len && sb.charAt(right)=='9'){
sb.setCharAt(right, '0');
right++;
sb.setCharAt(left, '0');
left--;
}
if(right==len){
sb.insert(0, '1');
//sb.append("1");
sb.setCharAt(right, '1');
}else{
sb.setCharAt(right, (char)(sb.charAt(right)+1));
if(right != left){
sb.setCharAt(left, (char)(sb.charAt(left)+1));
}
}
i = Integer.valueOf(new String(sb));
return i;
}
}
Where the above approach wins is when the density of palindromes per number tried is less when we go for higher numbers but for the range that is asked(0 to 1000) it would not be able to make much difference.
I am open to other approaches. I was thinking may be decoding the addition required to generate the next palindrome number should be faster and better approach instead of using strings the basic idea of both approaches are similar so should not be much difficult(though I am not sure).
I believe you want to check whether the number is a palindrome or not before you print it. You just need to seprate checking and printing like this:
if(num.length()>2)
{
boolean isPalindrome=true;
for(int i=0;i<=length/2;i++) //you compare one half, to the other
{
if(num.charAt(i)!=num.charAt(length-i))
isPalindrome=false;
}
if(isPalindrome)
System.out.println(num);
}
This should work for a number of any length.

Writing a method for factorial

I'm studying the code below in my textbook. It uses the combinations method and the factorial method to calculate the possible outcomes given n and k. My question is with the factorial method specifically the content in the for loop.
I understand everything else about the program but I don't understand the code i <=n in the for loop in the factorial method. What other part of the program is n referred to? I'm just not sure about the rationale behind i <= n or how the programmer comes up with that.
import acm.program.*;
public class combinations extends ConsoleProgram {
public void run(){
int n = readInt("Enter the number of objects in the set (n): ");
int k = readInt("Enter the number to be chosen (k): ");
println("C (" + n + ", " + k + ") = " + combinations (n, k) );
}
private int combinations (int n, int k){
return factorial (n) / (factorial (k) * factorial (n-k));
}
private int factorial (int n){
int result = 1;
for (int i = 1; i <= n; i++){
result *= i;
}
return result;
}
}
n is a parameter of the method: because the method is declared as int factorial(int n), you invoke it as (for example) factorial(5) to get the local variable n set to 5. (In formal terms, n is the parameter and 5 is the argument, though usually people don't bother to distinguish those two terms.)
So, a bit of math. Typically, when one deals with a mathematical expression, math conventions are frequently used. n is typically referred to some upper ceiling value that the method should refer to.
Essentially, the function definition for a factorial is this.
factorial(n) = { 1 if n = 0, n*factorial(n-1) otherwise.
The loop includes the final value of n, so you get the full expression of the function (if you didn't, your answer would be off by a factor of n every time.
You need i <= n because when you calculate factorial of 3! for example, you will have
3! = 3 * 2 * 1 <=> 1 * 2 * 3
So, you have your n, that is 3 and the i is 1, then 2, then 3 (n).
If you look closely you see that in loop for i take a values from 1 to n, so in i=n point for loop terminated. Loop for is created in this form to assure that factorial(0)=1. However, you can redesign this function in recursive style.

Categories