Understanding Java behaviour in recursive factorial - java

I created two recursive methods to calculate factorial as follows:
private int fact1(int n) {
if (n == 0 || n == 1)
return 1;
return n * fact1(--n);
}
private int fact2(int n) {
if (n == 0 || n == 1)
return 1;
return fact2(--n) * n;
}
When I call fact1(4) it returns 24. When I call fact2(4) it returns 6 (EDIT: is not returning 18 but 6). I know the second method is making 3 * 2 * 1, but I don't understand why not 4 * 3 * 2 * 1.
The same happens if I change the return to
//fact3(4) returns 60.
return (n + 1) * fact3(--n); // wrong
//fact4(4) returns 24
return fact4(--n) * (n + 1); // works
Why is the method exhibiting this behavior??
The question is about the different behaviour. I know n * fact(n-1) is the better way to solve it.
Can someone help me to understand the evaluation of this expression? Thanks!

It all comes down to the difference between these expressions:
return n * f(--n);
return f(--n) * n;
When n = 4, these expressions are evaluated like this:
return 4 * f(3);
return f(3) * 3;
Because the moment --n is evaluated, the value of n is decreased by 1.
This is how the prefix -- operator works.
It might help to recursively evaluate the entire expressions by hand. The first one:
// first
return 4 * f(3);
return 4 * 3 * f(2);
return 4 * 3 * 2 * f(1);
return 4 * 3 * 2 * 1;
// second
return f(3) * 3;
return f(2) * 2 * 3;
return f(1) * 1 * 2 * 3;
return 1 * 1 * 2 * 3;
On a related note, guess how this will be evaluated:
return f(n--) * n;
It will be:
return f(4) * 3;
Because here the postfix -- operator is used: the -1 decrement will be applied after the evaluation of n in f(...).

Related

codding optimization in java

hello i'm starting with java and i have to make a simulation of a rabbit population on 20 years and i barely passed the sixth year, can anyone help me please to optimize my program ?
it's in French but the first loop is for the months then I'll grow my rabbits and remove the dead ones
the next for the new born babies
if you need more details about the rabbit class tell me.
Ps i've already deleted a for loop.
thanks
package com.company;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
MTRandom MT = new MTRandom();
int nbMales;
int nbFemales;
int nbAnnee;
int[] init = {0x123, 0x234, 0x345, 0x456};
MT.setSeed(init);
//Bloc d'entrée
ArrayList<Rabbit> Rabbits = new ArrayList<>();//changer pour linked ?
System.out.println("Nombre de lapins males ?"); //creation males
nbMales = input.nextInt();
System.out.println("Nombre de lapins femelles ?");// creation femelles
nbFemales = input.nextInt();
System.out.println("Nombre d'année que va durer la simu ?");
nbAnnee = input.nextInt();
//for (int j = 0; j < 10; j++) {
//Rabbits.clear();
for (int i = 0; i < nbMales; i++) {
Rabbits.add(new Rabbit('m', 12, true));
}
for (int i = 0; i < nbFemales; i++) {
Rabbits.add(new Rabbit('f', 12, true));
}
//Bloc Principale
for (int i = 1; i <= nbAnnee * 12; i++) { // Defilement des Mois
for (int k = 0; k < Rabbits.size(); k++) {
Rabbits.get(k).setAge(); // incrementation de l'age des lapins en mois
Rabbits.removeIf(rabbit -> !rabbit.isAlive);
Rabbits.trimToSize();
}
for (int k = 0; k < Rabbits.size(); k++) { // boucle pour les projenitures
if (Rabbits.get(k).sexe == 'f' && Rabbits.get(k).isActiveSex && Rabbits.get(k).nbPortee > 0) {
double y = MT.nextDouble();
int n = 0;
if (y <= 0.3) {
n = 4;
}
if (y > 0.3 && y <= 0.5) {
n = 3;
}
if (y > 0.5 && y <= 0.7) {
n = 5;
}
if (y > 0.7 && y <= 0.85) {
n = 2;
}
if (y > 0.85) {
n = 6;
}
for (int l = 0; l < n; l++) {
double x = MT.nextDouble();
if (x <= 0.5) {
Rabbits.add(new Rabbit('m', 0, false));
Rabbits.get(k).setPortee();
} else if (x > 0.5) {
Rabbits.add(new Rabbit('f', 0, false));
Rabbits.get(k).setPortee();
}
}
}
if (i % 12 == 0) {
Rabbits.get(k).reinitPortee();
Rabbits.get(k).setChanceSurvie();
Rabbits.get(k).kill();
}
}
System.out.println("month " + i%12 + " year " + i/12 + " we have " + Rabbits.size()); // affichage chaque mois
}
System.out.println("Apres une simulation de " + nbAnnee + " nous avons :"); //affichage resultat final
System.out.println(" une population de " + Rabbits.size());
}
//}
}
Rabbit Class
package com.company;
public class Rabbit {
//Age
int ageMois;
int ageAnnee;
boolean isMature;
boolean isActiveSex = false;
double chanceSurvie = 0.5;
boolean isAlive = true;
//Les femelles
boolean isSterile = false;
char sexe;
int nbPortee = 0;
int nbPorteeInit;
MTRandom MT = new MTRandom();
public Rabbit(char sexe, int ageMois,boolean isMature){
int[] init ={0x123, 0x234, 0x345, 0x456};
MT.setSeed(init);
this.sexe = sexe;
this.ageMois = ageMois;
this.isMature = isMature;
double x = MT.nextDouble();
double y = MT.nextDouble();
if(this.sexe == 'f'){
if(x<0.1){
this.isSterile = true;
}
if(!this.isSterile){
if(y<=0.4){
this.nbPorteeInit = 6;
}
if(y>0.4 && y<=0.6){
this.nbPorteeInit = 5;
}
if(y>0.6 && y<=0.8){
this.nbPorteeInit = 7;
}
if(y>0.8 && y<=0.875){
this.nbPorteeInit = 4;
}
if(y>0.95&& y<=0.975){
this.nbPorteeInit = 8;
}
if(y>975){
this.nbPorteeInit = 3;
}
if(y>975){
this.nbPorteeInit = 9;
}
this.nbPortee = this.nbPorteeInit;
}
}
}
public void setAge(){ //en mois
double x = MT.nextDouble();
this.ageMois += 1;
this.ageAnnee = this.ageMois/12;
if(this.ageMois == 5) {
if (x <= 0.2) {
isMature = true;
if(!isSterile){
isActiveSex = true;
}
}
}
else if(this.ageMois == 6){
if (x >0.2 && x <= 0.5){
isMature = true;
if(!isSterile){
isActiveSex = true;}
}
}
else if(this.ageMois == 7){
if(x > 0.5 && x <= 0.8){
isMature = true;
if(!isSterile){
isActiveSex = true;}
}
}
else if(this.ageMois > 8){
if(x > 0.8){
isMature = true;
isActiveSex = true;
}
}
}
public void setChanceSurvie(){
if(this.isMature){
this.chanceSurvie = 0.75;
}
switch(this.ageAnnee){
case 8: this.chanceSurvie = 0.6;
case 9: this.chanceSurvie = 0.45;
case 10: this.chanceSurvie = 0.3;
case 11: this.chanceSurvie = 0.15;
case 12: this.chanceSurvie = 0;
}
}
public void setPortee(){
this.nbPortee -=1;
}
public void reinitPortee(){
this.nbPortee = this.nbPorteeInit;
}
public void kill(){
if(MT.nextDouble() >this.chanceSurvie){
isAlive = false;
}
}
}
5 years experience
month 1 year 0 we have 6
month 2 year 0 we have 11
month 3 year 0 we have 11
month 4 year 0 we have 11
month 5 year 0 we have 11
month 6 year 0 we have 20
month 7 year 0 we have 39
month 8 year 0 we have 45
month 9 year 0 we have 45
month 10 year 0 we have 45
month 11 year 0 we have 58
month 0 year 1 we have 116
month 1 year 1 we have 20
month 2 year 1 we have 33
month 3 year 1 we have 39
month 4 year 1 we have 39
month 5 year 1 we have 39
month 6 year 1 we have 69
month 7 year 1 we have 113
month 8 year 1 we have 151
month 9 year 1 we have 160
month 10 year 1 we have 164
month 11 year 1 we have 206
month 0 year 2 we have 310
month 1 year 2 we have 116
month 2 year 2 we have 160
month 3 year 2 we have 167
month 4 year 2 we have 167
month 5 year 2 we have 167
month 6 year 2 we have 366
month 7 year 2 we have 621
month 8 year 2 we have 713
month 9 year 2 we have 756
month 10 year 2 we have 758
month 11 year 2 we have 1150
month 0 year 3 we have 2032
month 1 year 3 we have 458
month 2 year 3 we have 664
month 3 year 3 we have 692
month 4 year 3 we have 692
month 5 year 3 we have 692
month 6 year 3 we have 1368
month 7 year 3 we have 2312
month 8 year 3 we have 2808
month 9 year 3 we have 2891
month 10 year 3 we have 2896
month 11 year 3 we have 4204
month 0 year 4 we have 7320
month 1 year 4 we have 1858
month 2 year 4 we have 2604
month 3 year 4 we have 2653
month 4 year 4 we have 2653
month 5 year 4 we have 2653
month 6 year 4 we have 5456
month 7 year 4 we have 9401
month 8 year 4 we have 11077
month 9 year 4 we have 11303
month 10 year 4 we have 11321
month 11 year 4 we have 17109
month 0 year 5 we have 29899
MT => Pseudo Random Numbers generator:
package com.company;
import java.util.Random;
/**
* #version 1.0
* #author David Beaumont, Copyright 2005
* <p>
* A Java implementation of the MT19937 (Mersenne Twister) pseudo
* random number generator algorithm based upon the original C code
* by Makoto Matsumoto and Takuji Nishimura (see
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</a> for
* more information.
* <p>
* As a subclass of java.util.Random this class provides a single
* canonical method next() for generating bits in the pseudo random
* number sequence. Anyone using this class should invoke the public
* inherited methods (nextInt(), nextFloat etc.) to obtain values as
* normal. This class should provide a drop-in replacement for the
* standard implementation of java.util.Random with the additional
* advantage of having a far longer period and the ability to use a
* far larger seed value.
* <p>
* This is <b>not</b> a cryptographically strong source of randomness
* and should <b>not</b> be used for cryptographic systems or in any
* other situation where true random numbers are required.
* <p>
* <!-- Creative Commons License -->
* <img alt="CC-GNU LGPL" border="0" src="http://creativecommons.org/images/public/cc-LGPL-a.png" /><br />
* This software is licensed under the CC-GNU LGPL.
* <!-- /Creative Commons License -->
*
* <!--
* <rdf:RDF xmlns="http://web.resource.org/cc/"
* xmlns:dc="http://purl.org/dc/elements/1.1/"
* xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
*
* <Work rdf:about="">
* <license rdf:resource="http://creativecommons.org/licenses/LGPL/2.1/" />
* <dc:type rdf:resource="http://purl.org/dc/dcmitype/Software" />
* </Work>
*
* <License rdf:about="http://creativecommons.org/licenses/LGPL/2.1/">
* <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
* <permits rdf:resource="http://web.resource.org/cc/Distribution" />
* <requires rdf:resource="http://web.resource.org/cc/Notice" />
* <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
* <requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
* <requires rdf:resource="http://web.resource.org/cc/SourceCode" />
* </License>
*
* </rdf:RDF>
* -->
*
*/
public class MTRandom extends Random {
/**
* Auto-generated serial version UID. Note that MTRandom does NOT
* support serialisation of its internal state and it may even be
* necessary to implement read/write methods to re-seed it properly.
* This is only here to make Eclipse shut up about it being missing.
*/
private static final long serialVersionUID = -515082678588212038L;
// Constants used in the original C implementation
private final static int UPPER_MASK = 0x80000000;
private final static int LOWER_MASK = 0x7fffffff;
private final static int N = 624;
private final static int M = 397;
private final static int MAGIC[] = { 0x0, 0x9908b0df };
private final static int MAGIC_FACTOR1 = 1812433253;
private final static int MAGIC_FACTOR2 = 1664525;
private final static int MAGIC_FACTOR3 = 1566083941;
private final static int MAGIC_MASK1 = 0x9d2c5680;
private final static int MAGIC_MASK2 = 0xefc60000;
private final static int MAGIC_SEED = 19650218;
private final static long DEFAULT_SEED = 5489L;
// Internal state
private transient int[] mt;
private transient int mti;
private transient boolean compat = false;
// Temporary buffer used during setSeed(long)
private transient int[] ibuf;
/**
* The default constructor for an instance of MTRandom. This invokes
* the no-argument constructor for java.util.Random which will result
* in the class being initialised with a seed value obtained by calling
* System.currentTimeMillis().
*/
public MTRandom() { }
/**
* This version of the constructor can be used to implement identical
* behaviour to the original C code version of this algorithm including
* exactly replicating the case where the seed value had not been set
* prior to calling genrand_int32.
* <p>
* If the compatibility flag is set to true, then the algorithm will be
* seeded with the same default value as was used in the original C
* code. Furthermore the setSeed() method, which must take a 64 bit
* long value, will be limited to using only the lower 32 bits of the
* seed to facilitate seamless migration of existing C code into Java
* where identical behaviour is required.
* <p>
* Whilst useful for ensuring backwards compatibility, it is advised
* that this feature not be used unless specifically required, due to
* the reduction in strength of the seed value.
*
* #param compatible Compatibility flag for replicating original
* behaviour.
*/
public MTRandom(boolean compatible) {
super(0L);
compat = compatible;
setSeed(compat?DEFAULT_SEED:System.currentTimeMillis());
}
/**
* This version of the constructor simply initialises the class with
* the given 64 bit seed value. For a better random number sequence
* this seed value should contain as much entropy as possible.
*
* #param seed The seed value with which to initialise this class.
*/
public MTRandom(long seed) {
super(seed);
}
/**
* This version of the constructor initialises the class with the
* given byte array. All the data will be used to initialise this
* instance.
*
* #param buf The non-empty byte array of seed information.
* #throws NullPointerException if the buffer is null.
* #throws IllegalArgumentException if the buffer has zero length.
*/
public MTRandom(byte[] buf) {
super(0L);
setSeed(buf);
}
/**
* This version of the constructor initialises the class with the
* given integer array. All the data will be used to initialise
* this instance.
*
* #param buf The non-empty integer array of seed information.
* #throws NullPointerException if the buffer is null.
* #throws IllegalArgumentException if the buffer has zero length.
*/
public MTRandom(int[] buf) {
super(0L);
setSeed(buf);
}
// Initializes mt[N] with a simple integer seed. This method is
// required as part of the Mersenne Twister algorithm but need
// not be made public.
private final void setSeed(int seed) {
// Annoying runtime check for initialisation of internal data
// caused by java.util.Random invoking setSeed() during init.
// This is unavoidable because no fields in our instance will
// have been initialised at this point, not even if the code
// were placed at the declaration of the member variable.
if (mt == null) mt = new int[N];
// ---- Begin Mersenne Twister Algorithm ----
mt[0] = seed;
for (mti = 1; mti < N; mti++) {
mt[mti] = (MAGIC_FACTOR1 * (mt[mti-1] ^ (mt[mti-1] >>> 30)) + mti);
}
// ---- End Mersenne Twister Algorithm ----
}
/**
* This method resets the state of this instance using the 64
* bits of seed data provided. Note that if the same seed data
* is passed to two different instances of MTRandom (both of
* which share the same compatibility state) then the sequence
* of numbers generated by both instances will be identical.
* <p>
* If this instance was initialised in 'compatibility' mode then
* this method will only use the lower 32 bits of any seed value
* passed in and will match the behaviour of the original C code
* exactly with respect to state initialisation.
*
* #param seed The 64 bit value used to initialise the random
* number generator state.
*/
public final synchronized void setSeed(long seed) {
if (compat) {
setSeed((int)seed);
} else {
// Annoying runtime check for initialisation of internal data
// caused by java.util.Random invoking setSeed() during init.
// This is unavoidable because no fields in our instance will
// have been initialised at this point, not even if the code
// were placed at the declaration of the member variable.
if (ibuf == null) ibuf = new int[2];
ibuf[0] = (int)seed;
ibuf[1] = (int)(seed >>> 32);
setSeed(ibuf);
}
}
/**
* This method resets the state of this instance using the byte
* array of seed data provided. Note that calling this method
* is equivalent to calling "setSeed(pack(buf))" and in particular
* will result in a new integer array being generated during the
* call. If you wish to retain this seed data to allow the pseudo
* random sequence to be restarted then it would be more efficient
* to use the "pack()" method to convert it into an integer array
* first and then use that to re-seed the instance. The behaviour
* of the class will be the same in both cases but it will be more
* efficient.
*
* #param buf The non-empty byte array of seed information.
* #throws NullPointerException if the buffer is null.
* #throws IllegalArgumentException if the buffer has zero length.
*/
public final void setSeed(byte[] buf) {
setSeed(pack(buf));
}
/**
* This method resets the state of this instance using the integer
* array of seed data provided. This is the canonical way of
* resetting the pseudo random number sequence.
*
* #param buf The non-empty integer array of seed information.
* #throws NullPointerException if the buffer is null.
* #throws IllegalArgumentException if the buffer has zero length.
*/
public final synchronized void setSeed(int[] buf) {
int length = buf.length;
if (length == 0) throw new IllegalArgumentException("Seed buffer may not be empty");
// ---- Begin Mersenne Twister Algorithm ----
int i = 1, j = 0, k = (N > length ? N : length);
setSeed(MAGIC_SEED);
for (; k > 0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * MAGIC_FACTOR2)) + buf[j] + j;
i++; j++;
if (i >= N) { mt[0] = mt[N-1]; i = 1; }
if (j >= length) j = 0;
}
for (k = N-1; k > 0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * MAGIC_FACTOR3)) - i;
i++;
if (i >= N) { mt[0] = mt[N-1]; i = 1; }
}
mt[0] = UPPER_MASK; // MSB is 1; assuring non-zero initial array
// ---- End Mersenne Twister Algorithm ----
}
/**
* This method forms the basis for generating a pseudo random number
* sequence from this class. If given a value of 32, this method
* behaves identically to the genrand_int32 function in the original
* C code and ensures that using the standard nextInt() function
* (inherited from Random) we are able to replicate behaviour exactly.
* <p>
* Note that where the number of bits requested is not equal to 32
* then bits will simply be masked out from the top of the returned
* integer value. That is to say that:
* <pre>
* mt.setSeed(12345);
* int foo = mt.nextInt(16) + (mt.nextInt(16) << 16);</pre>
* will not give the same result as
* <pre>
* mt.setSeed(12345);
* int foo = mt.nextInt(32);</pre>
*
* #param bits The number of significant bits desired in the output.
* #return The next value in the pseudo random sequence with the
* specified number of bits in the lower part of the integer.
*/
protected final synchronized int next(int bits) {
// ---- Begin Mersenne Twister Algorithm ----
int y, kk;
if (mti >= N) { // generate N words at one time
// In the original C implementation, mti is checked here
// to determine if initialisation has occurred; if not
// it initialises this instance with DEFAULT_SEED (5489).
// This is no longer necessary as initialisation of the
// Java instance must result in initialisation occurring
// Use the constructor MTRandom(true) to enable backwards
// compatible behaviour.
for (kk = 0; kk < N-M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >>> 1) ^ MAGIC[y & 0x1];
}
for (;kk < N-1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ MAGIC[y & 0x1];
}
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ MAGIC[y & 0x1];
mti = 0;
}
y = mt[mti++];
// Tempering
y ^= (y >>> 11);
y ^= (y << 7) & MAGIC_MASK1;
y ^= (y << 15) & MAGIC_MASK2;
y ^= (y >>> 18);
// ---- End Mersenne Twister Algorithm ----
return (y >>> (32-bits));
}
// This is a fairly obscure little code section to pack a
// byte[] into an int[] in little endian ordering.
/**
* This simply utility method can be used in cases where a byte
* array of seed data is to be used to repeatedly re-seed the
* random number sequence. By packing the byte array into an
* integer array first, using this method, and then invoking
* setSeed() with that; it removes the need to re-pack the byte
* array each time setSeed() is called.
* <p>
* If the length of the byte array is not a multiple of 4 then
* it is implicitly padded with zeros as necessary. For example:
* <pre> byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }</pre>
* becomes
* <pre> int[] { 0x04030201, 0x00000605 }</pre>
* <p>
* Note that this method will not complain if the given byte array
* is empty and will produce an empty integer array, but the
* setSeed() method will throw an exception if the empty integer
* array is passed to it.
*
* #param buf The non-null byte array to be packed.
* #return A non-null integer array of the packed bytes.
* #throws NullPointerException if the given byte array is null.
*/
public static int[] pack(byte[] buf) {
int k, blen = buf.length, ilen = ((buf.length+3) >>> 2);
int[] ibuf = new int[ilen];
for (int n = 0; n < ilen; n++) {
int m = (n+1) << 2;
if (m > blen) m = blen;
for (k = buf[--m]&0xff; (m & 0x3) != 0; k = (k << 8) | buf[--m]&0xff);
ibuf[n] = k;
}
return ibuf;
}
}

Using Recursion to change digits in a number

I made this method for an assignment in class. To count the number of '1's appearing in any given number. I would like to expand on this and learn how to take a number and if it is even number adds one to it. If it is an odd number subtract one from it using recursion and return that changed number.
public static int countOnes(int n){
if(n < 0){
return countOnes(n*-1);
}
if(n == 0){
return 0;
}
if(n%10 == 1){
return 1 + countOnes(n/10);
}else
return countOnes(n/10);
}
0 would = 1 27 would = 36 so on. I would appreciate any help that is given.
You quite often find that using private method in a recursive solution makes your code much clearer.
/**
* Twiddles one digit.
*/
private static int twiddleDigit(int n) {
return (n & 1) == 1 ? n - 1 : n + 1;
}
/**
* Adds one to digits that are even, subtracts one from digits that are odd.
*/
public static int twiddleDigits(int n) {
if (n < 10) return twiddleDigit(n);
return twiddleDigits(n / 10) * 10 + twiddleDigit(n % 10);
}

What is the logic of the recursion

Here is I have a factorial code using recursion.
class Factorial
{
public static void main(String args[])
{
Factorial f = new Factorial();
System.out.println(f.fact(Integer.parseInt(args[0])));
}
private int fact(int num)
{
int result;
if(num == 1)
return 1;
result = fact(num - 1) * num;
return result;
}
}
Now to run this program, I did this
D:\>java Factorial 3
Now according to the logic when it enters the fact function, where num = 3, so it will skip to
result = fact(num - 1) * num;
Here it will become
result = fact(3 - 1) * num;
i.e. result = fact(2) * num;
In this step, I am little confused Does it execute whole step i.e.
result = fact(num - 1) * num;
or just the fact(num - 1)
According to the logic, what it should do is call the fact function. So, the control of the program again reaches to the start of the fact function where num = 2. It will again skip to
result = fact(num - 1) * num;
So, it will become
result = fact(2 - 1) * num;
i.e. result = fact(1) * num;
Now again, it should call the fact function without executing the whole syntax & again reaches to the start of the fact method where num = 1. This time num == 1 will be matched & 1 will be returned. Now it will return to
result = fact(num - 1) * num;
So, it will become
result = fact(1 - 1) * num;
i.e. result = fact(0) * num;
Now what will happen next ?
Am I going right ? If not what will be the correction ?
I dont clearly understand the flow of this recursion program.
So, it will become
result = fact(1 - 1) * num;
Nope. For num = 2,
result = fact(num - 1) * num;
becomes
result = 1 * num; // i.e. 1 * 2
fact returns a value, which means the entire call has to be replace with that value.
Not sure why you would even think num changes at all. You have no num = ... in your code.
I added some trace into the program. Execute it and see the output. Should be easy to follow.
package snippet;
class Factorial {
public static void main(String args[]) {
Factorial f = new Factorial();
System.out.println(f.fact(Integer.parseInt("5")));
}
private int fact(int num) {
int result;
if (num == 1)
return 1;
result = fact(num - 1) * num;
System.out.println("fact(" + num + ") = " + result + " = fact(" + (num - 1) + ") * " + num);
return result;
}
}
fact(2) = 2 = fact(1) * 2
fact(3) = 6 = fact(2) * 3
fact(4) = 24 = fact(3) * 4
fact(5) = 120 = fact(4) * 5
120
Your logic is right but you have made 3 basic errors.
if we take your example;
First you run the program
D:\>java Factorial 3
then you have your first mistake because according to the logic all "num" have to be replaced by "3". So you get:
result = fact(3 - 1) * 3;
ie:
result = fact(2)*3;
then we have the second mistake because according to the definition of fact(num),
fact(2) = fact(2-1)*2
so we actually have
result = (fact(2-1)*2)*3
which is evaluated in
result = (fact(1)*2)*3
and here stand the third mistake because again according to fact(num) definition : fact(1) = 1 and not fact(1) = fact(1-1)*1
so we finally have:
result = ((1)*2)*3
To be more explicit if you follow all call sequence in the debugger you 'll have something like this( I put between brackets the value of the variable):
private int fact(num{3})
{
int result;
if(num{3}== 1)
return 1;
result = fact(num{3} - 1) * num{3};
private int fact(num{3-1})
{
int result;
if(num{3-1}== 1)
result = fact(num{3-1} - 1) * num{3-1};
private int fact(num{3-1-1})
{
int result;
if(num{3-1-1}== 1)
return 1;
}
return result{1*{3-1}};
}
return result{{1*{3-1}}*3};
}
Unless we hit the stop condition:
fact(num) = fact(num - 1) * num;
Therefore:
fact(3) = fact(3 - 1) * 3;
Keeping in mind that fact(1) = 1 (from the if statement early in the fact() method):
fact(3) = fact(2) * 3;
fact(2) = fact(1) * 2;
fact(1) = 1;
Replacing each element:
fact(3) = 1 * 2 * 3;
The recursion is used to repeatedly dive deeper into the process until a stop condition is encountered - in this case when num = 1.
The call f.fact(3) is expanding through the following steps:
1. result = fact(3 - 1) * 3 = fact(2) * 3
2. result = (fact(2 - 1) * 2) * 3 = (fact(1) * 2) * 3
3. result = 1 * 2 * 3 because fact(1) returns 1.
Your implementation is correct, But it will never reach fact(1-1) * 1 state ,as you return from method at if(num == 1).
num variable is limited to scope of method parameter. So for every call to fact method num variable is assigned a new value (i.e. num-1) and which is limited to that parameter scope only. So when fact(num-1) returns , value of num will be the original value and not the num-1.
The flow of your example is like this
step 1. fact(3)*3; //calling the function with num value 3
step 2. fact(2)*2; //calling fact() method again with num=2
step 3. fact(1)*1; //now num == 1 will be matched & 1 will be returned.
i. e.,
1 * 1 = 1; //now, steps 2 and 1 will be performed respectively
step 2. 1 * 2 = 2;
step 1. 2 * 3 = 6;
So, the final answer will be 6
Note: In step 3, the value is returned, so it will not again call this result = fact(0) * num; //which you have mentioned in question.

Java Math Formula Loops

how do you add formula n! = 1 * 2 * 3 * i in java that it will be in a loop. An example is if the user inputs 5 the output will be 1 * 2 * 3 * 4 * 5 = 120. If you input 4 the output will be 1 * 2 * 3 * 4 = 24
Do like this:
public int formulaMethod(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
Hope it helps
You can use recursion to solve this problem:
public static int factorial(int n)
{
if (n == 0)
{
return 1;
}
else
{
return (n * factorial(n-1));
}
}

How is the result produce in a recursion?

First Code: a = 5
if (a==0)
return 1;
return a * xample(a-1);
My tracing:
5==0 FALSE
skip return 1
return 5 * xample(5-1)
so, a = 4
go back inside the method
4==0 FALSE
skip return 1
return 5 * xample(4-1)
so, a = 3
go back inside the method
3==0 FALSE
skip return 1
return 5 * xample(3-1)
so, a = 2
go back inside the method
2==0 FALSE
skip return 1
return 5 * xample(2-1)
so, a = 1
go back inside the method
1==0 FALSE
skip return 1
return 5 * xample(1-1)
so, a = 0
go back inside the method
0==0 TRUE
return 1
so last value is 1, how come the real last value is 120?
Second Code: a = 5
if (a<1)
return 1;
else
return a + xample(a/5);
how come the answer is 7?
Third Code: a = 5
a--;
if (a>0)
{
xample(a);
}
return a;
How come the answer is 4???
In the following code :
if (a==0)
return 1;
return a * xample(a-1);
If a is 5 :
return 5 * xample (5 - 1) =
5 * 4 * xample (4 - 1) =
5 * 4 * 3 * xample (3 - 1) =
5 * 4 * 3 * 2 * xample (2 - 1) =
5 * 4 * 3 * 2 * 1 * xample (1 - 1) =
5 * 4 * 3 * 2 * 1 * 1 = 120

Categories

Resources