Fibonacci using a recursive method gives me stack overflow - java

public static int rFib(int n) {
if(n == 0) {
return 0;
}
if(n == 1) {
return 1;
}
return n + rFib(n-1);
}
I am trying to find the largest number that will compute in under 60 seconds. Then I will use an iterative method to compare. Any number greater than 10,000 gives a stack-overflow error. How do I avoid this?

One solution to this recursion problem is to break the recursion using dynamic programming. For example, memoization can be applied and allow you to implement it like
private static Map<Integer, Integer> memo = new HashMap<>();
static {
memo.put(0, 0);
memo.put(1, 1);
}
public static int rFib(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
int r = rFib(n - 2) + rFib(n - 1);
memo.put(n, r);
return r;
}

Unfortunately, you have come across the problem which is both the single most-used example for understanding recursion and almost the single worst application to apply recursion to.
It's really simple to understand recursion from the fibonacci because it's a really trivial recursive algorithm for you to explain to somebody and understand... Which means it's great for programming recursion, right? Unfortunately, no.
I apologize if I'm going to tell you things you already know, but I know that fibonacci is one of the first examples in introductory programming so I'm assuming that's where you're coming from.
There's a thing in programming called a stack. It's literally called this because it's like a stack of papers. When you call a function, it puts onto the stack all the information needed to call the function, pass the arguments, and know how to return from the function (and some other administrative stuff). When that function recursively calls itself, it puts another sheet on top of the stack. Then that function puts another sheet. These sheets aren't removed until the function finishes... But since one function can't finish before the other one finishes, it just grows and grows and grows.
And the stack is only so big. Purposely. To avoid this problem.
Normally, recursion isn't used for such deep problems. (Tail-call-recursive people: ignore this; if you don't know what tail-call-recusion is: also ignore this.)
The way to fix this is to not do it. It's generally recognized that in nearly every arbitrarily-recursive function application, a for loop will work better (and faster).

Related

Infinite recursive call [duplicate]

I am trying to implement a tail-recursive factorial calculator but I am still getting a stack overflow. Can anyone help me out in figuring out why?
I have read that Java 8 supports Tail call optimization, but I am thinking I must not be implementing it correctly.
I have read that it is possible using lambda expressions. I am not sure I fully understand this concept but I am still reading.
I am just looking for any advice on how to get this to use real tail call optimization, lambda expressions or however I can.
code:
package factorielRecursiveTerminale;
import java.math.BigInteger;
import java.util.Scanner;
public class factorielRecursiveTerminale {
public static BigInteger factoriel(BigInteger n, BigInteger m) {
if (n.compareTo(BigInteger.ZERO) < 1) return m;
return factoriel(n.subtract(BigInteger.ONE), n.multiply(m));
}
public static BigInteger fact(int n) { //convertir l'entree en BigInteger et lancer la recursion
if(n < 0) {
return BigInteger.valueOf(-1);
}
BigInteger b = BigInteger.valueOf(n);
return factoriel(b, BigInteger.ONE);
}
public static void runBigFact() { //gestion des erreurs + boucle d'entree de valeurs.
String valeurRecu = "";
int valeur;
BigInteger resultat;
System.out.println("Calcul Factoriel\n");
while(!valeurRecu.contentEquals("q")){
System.out.println("Entrer la valeur a calculer (q - quitter) : ");
Scanner entree = new Scanner(System.in);
valeurRecu = entree.nextLine();
if (valeurRecu.contentEquals("q")) entree.close();
else {
try {
valeur = Integer.parseInt(valeurRecu);
}catch (NumberFormatException e){
System.out.println("Pas un entier. Essayer encore.\n");
continue;
}
try {
resultat = fact(valeur);
if(resultat.compareTo(BigInteger.valueOf(-1)) == 0) {
System.out.println("Valeur negative. Essayer encore.\n");
}
else System.out.println("Factoriel " + valeur + " -> " + fact(valeur) + "\n");
} catch(StackOverflowError e) {
System.out.println("Depassement de la pile. Essayer un entier plus petit.\n");
continue;
}
}
}
System.out.println("Au revoir! :)\n");
}
public static void main(String[] args) {
runBigFact();
}
}
I have read that JAVA 8 supports Tail call optimization, but I am thinking I must not be implementing it correctly.
Then you have read wrong. Or, you've read a correct statement but didn't interpret it correctly.
Java, the language, does not support tail call recursion. It never has. It probably never will*.
However, java, the VM, has a few features that make it easier for other, non-java languages which nevertheless compile into class files to run on a java runtime, to support TCO. That's, presumably, what you read about.
I am just looking for any advice on how to get this to use real tail call optimization, lambda expressions or however I can.
Write it in scala or some such.
Seriously, how does java not have TCO???
TCO is pricey: Java has this rule that when errors occur you get a stack trace, and stack traces are a well defined concept that, crucially, tracks 1 stack frame for each logical call. This cannot continue if TCO exists. There are options, of course: Each individual frame on stack could gain a 'counter' so that the stack trace remains a smallish memory footprint while correctly representing 'and this sequence of calls has recurred 8190581 times'. It's also a boatload of text in the lang spec about how it works, when it does and doesn't kick in, and what it all means, and any additional pages in the spec are maintenance burdens forever - it's not a case of 'it is strictly superior to add TCO to java so when we get around to it, slam dunk, and any Pull Requests with the feature will be integrated immediately'.
Furthermore, TCO as a model is a way of doing things, but it's not the only way. For anything that could be written as a TCO-recursive application, it is generally not all that difficult to refactor that into a loop-based, non-recursing algorithm. Contrast to, say, yield-based async operations, where you can of course rewrite (hey, it's all turing machines), but the rewrite would be difficult, and the resulting code considerably harder to understand. I don't want to get into the value (or lack thereof) of yield/async style coding, just making the point that TCO does not have that veneer of 'ah, but, if TCO is a good idea, then only TCO will do'.
I don't have the links off-hand, but statements in this vein have been said by those who hold quite a bit of sway over the future of java, such as Brian Goetz, Mark Reinhold, etc. If you are really dedicated to try to see this added to java, I suggest you search the web for these statements and then try to shape some arguments specifically to address the concerns they state. Because if you can't convince those folks, it's never going to happen.
So what do I do in java?
Don't use recursion; use while or for instead.
UPDATE: What about that blog entry?
In comments you have linked to this blog entry. That's.. not TCO.
That's using lambdas to write a framework that lets you more or less emulate TCO, but it isn't TCO. The blog describes a little framework - and thus, you need all that stuff they pasted: The TailCall interface in particular.
That code works like this:
Your 'recursive' method isn't recursive at all, it always returns quickly without calling itself.
It returns a lambda which may call itself, though. But, as we just covered, calling yourself returns quickly without recursion, and it returns a function.
The framework will execute your function, which produces, usually, a function (or an actual result). It loops (so no recursion), repeatedly applying the process of: "Call the function. If it returns a function, then loop. If it returns a result, okay, that's the result we wanted so just return that".
That describes what TCO tries to accomplish (repeatedly invoke the same function over and over with different arguments until a hardcoded edge case is reached, and then reverse back out), but doesn't use TCO to do it.
Hence, that blog post saying 'look, TCO in java!' is misleading.
It's like me saying: "Look, paintbrushes on tunnels walls!" and describing how to use cans of spray paint to paint the tunnel wall in a way that looks like it was hand brushed. That is nice, but it's misleading to call it 'paintbrushing a wall'. At best you can say: "Looking to make paintbrush style art in tunnels? Well, you can't, and I can't fix that, but I can tell you how to get similar results!".
*) Never say never and all that, but I mean: There are no plans on the horizon, and the plans for the future of the java platform go many years into the future and are quite public. I'd take 1 to 40 odds on 'java (the language) does not have tail call recursion within 4 years' and still take that bet.
You may find this useful. I was able to get some improvement over your previous attempt but in this case it is not the size of the BigInteger object that causes the SO. On my machine, both of these methods result in a Stack Overflow between 14000 and 15000 for n. The simpleLong is just a basic recursive method to decrement the Long and it still blows up at 15000. Both succeed at 14000.
public static void main(String[] args) {
count = 0;
long n = 14000;
simpleLong(n);
factoriel(BigInteger.valueOf(n));
}
static BigInteger factoriel(BigInteger n) {
if (n.compareTo(BigInteger.TWO) == 1) {
return factoriel(n.subtract(BigInteger.ONE)).multiply(n);
}
return n;
}
static long simpleLong(long n) {
if (n > 1) {
simpleLong(n-1);
}
return n;
}

Tail recursive function still blowing the stack in Java

I am trying to implement a tail-recursive factorial calculator but I am still getting a stack overflow. Can anyone help me out in figuring out why?
I have read that Java 8 supports Tail call optimization, but I am thinking I must not be implementing it correctly.
I have read that it is possible using lambda expressions. I am not sure I fully understand this concept but I am still reading.
I am just looking for any advice on how to get this to use real tail call optimization, lambda expressions or however I can.
code:
package factorielRecursiveTerminale;
import java.math.BigInteger;
import java.util.Scanner;
public class factorielRecursiveTerminale {
public static BigInteger factoriel(BigInteger n, BigInteger m) {
if (n.compareTo(BigInteger.ZERO) < 1) return m;
return factoriel(n.subtract(BigInteger.ONE), n.multiply(m));
}
public static BigInteger fact(int n) { //convertir l'entree en BigInteger et lancer la recursion
if(n < 0) {
return BigInteger.valueOf(-1);
}
BigInteger b = BigInteger.valueOf(n);
return factoriel(b, BigInteger.ONE);
}
public static void runBigFact() { //gestion des erreurs + boucle d'entree de valeurs.
String valeurRecu = "";
int valeur;
BigInteger resultat;
System.out.println("Calcul Factoriel\n");
while(!valeurRecu.contentEquals("q")){
System.out.println("Entrer la valeur a calculer (q - quitter) : ");
Scanner entree = new Scanner(System.in);
valeurRecu = entree.nextLine();
if (valeurRecu.contentEquals("q")) entree.close();
else {
try {
valeur = Integer.parseInt(valeurRecu);
}catch (NumberFormatException e){
System.out.println("Pas un entier. Essayer encore.\n");
continue;
}
try {
resultat = fact(valeur);
if(resultat.compareTo(BigInteger.valueOf(-1)) == 0) {
System.out.println("Valeur negative. Essayer encore.\n");
}
else System.out.println("Factoriel " + valeur + " -> " + fact(valeur) + "\n");
} catch(StackOverflowError e) {
System.out.println("Depassement de la pile. Essayer un entier plus petit.\n");
continue;
}
}
}
System.out.println("Au revoir! :)\n");
}
public static void main(String[] args) {
runBigFact();
}
}
I have read that JAVA 8 supports Tail call optimization, but I am thinking I must not be implementing it correctly.
Then you have read wrong. Or, you've read a correct statement but didn't interpret it correctly.
Java, the language, does not support tail call recursion. It never has. It probably never will*.
However, java, the VM, has a few features that make it easier for other, non-java languages which nevertheless compile into class files to run on a java runtime, to support TCO. That's, presumably, what you read about.
I am just looking for any advice on how to get this to use real tail call optimization, lambda expressions or however I can.
Write it in scala or some such.
Seriously, how does java not have TCO???
TCO is pricey: Java has this rule that when errors occur you get a stack trace, and stack traces are a well defined concept that, crucially, tracks 1 stack frame for each logical call. This cannot continue if TCO exists. There are options, of course: Each individual frame on stack could gain a 'counter' so that the stack trace remains a smallish memory footprint while correctly representing 'and this sequence of calls has recurred 8190581 times'. It's also a boatload of text in the lang spec about how it works, when it does and doesn't kick in, and what it all means, and any additional pages in the spec are maintenance burdens forever - it's not a case of 'it is strictly superior to add TCO to java so when we get around to it, slam dunk, and any Pull Requests with the feature will be integrated immediately'.
Furthermore, TCO as a model is a way of doing things, but it's not the only way. For anything that could be written as a TCO-recursive application, it is generally not all that difficult to refactor that into a loop-based, non-recursing algorithm. Contrast to, say, yield-based async operations, where you can of course rewrite (hey, it's all turing machines), but the rewrite would be difficult, and the resulting code considerably harder to understand. I don't want to get into the value (or lack thereof) of yield/async style coding, just making the point that TCO does not have that veneer of 'ah, but, if TCO is a good idea, then only TCO will do'.
I don't have the links off-hand, but statements in this vein have been said by those who hold quite a bit of sway over the future of java, such as Brian Goetz, Mark Reinhold, etc. If you are really dedicated to try to see this added to java, I suggest you search the web for these statements and then try to shape some arguments specifically to address the concerns they state. Because if you can't convince those folks, it's never going to happen.
So what do I do in java?
Don't use recursion; use while or for instead.
UPDATE: What about that blog entry?
In comments you have linked to this blog entry. That's.. not TCO.
That's using lambdas to write a framework that lets you more or less emulate TCO, but it isn't TCO. The blog describes a little framework - and thus, you need all that stuff they pasted: The TailCall interface in particular.
That code works like this:
Your 'recursive' method isn't recursive at all, it always returns quickly without calling itself.
It returns a lambda which may call itself, though. But, as we just covered, calling yourself returns quickly without recursion, and it returns a function.
The framework will execute your function, which produces, usually, a function (or an actual result). It loops (so no recursion), repeatedly applying the process of: "Call the function. If it returns a function, then loop. If it returns a result, okay, that's the result we wanted so just return that".
That describes what TCO tries to accomplish (repeatedly invoke the same function over and over with different arguments until a hardcoded edge case is reached, and then reverse back out), but doesn't use TCO to do it.
Hence, that blog post saying 'look, TCO in java!' is misleading.
It's like me saying: "Look, paintbrushes on tunnels walls!" and describing how to use cans of spray paint to paint the tunnel wall in a way that looks like it was hand brushed. That is nice, but it's misleading to call it 'paintbrushing a wall'. At best you can say: "Looking to make paintbrush style art in tunnels? Well, you can't, and I can't fix that, but I can tell you how to get similar results!".
*) Never say never and all that, but I mean: There are no plans on the horizon, and the plans for the future of the java platform go many years into the future and are quite public. I'd take 1 to 40 odds on 'java (the language) does not have tail call recursion within 4 years' and still take that bet.
You may find this useful. I was able to get some improvement over your previous attempt but in this case it is not the size of the BigInteger object that causes the SO. On my machine, both of these methods result in a Stack Overflow between 14000 and 15000 for n. The simpleLong is just a basic recursive method to decrement the Long and it still blows up at 15000. Both succeed at 14000.
public static void main(String[] args) {
count = 0;
long n = 14000;
simpleLong(n);
factoriel(BigInteger.valueOf(n));
}
static BigInteger factoriel(BigInteger n) {
if (n.compareTo(BigInteger.TWO) == 1) {
return factoriel(n.subtract(BigInteger.ONE)).multiply(n);
}
return n;
}
static long simpleLong(long n) {
if (n > 1) {
simpleLong(n-1);
}
return n;
}

Developing a recursive program to calculate an answer

I need to develop a recursive program that can calculate the result 1/i+2/(i-1)+3/(i-2)+…+(i-1)/2+i/1 when f3(1, i) is called.
public class Project4f3
{
public static int f3(int x, int y)
// I know that it has to have a stop termination and i think that is when x==y, but im not sure
if (x==y) return ??
else return f3(x+1,y-1)
// don't think this is right but this is where I am at right now
}
public static void main(String[] args)
{
System.out.print(f3(1,i));
}
}
To develop a recursive algorithm, you need to think about two things:
What are the base cases? These are the cases that can be computed directly. For instance, if n == 1, you can compute the answer directly.
What are the recursive cases? These are the cases that assume that the solution to a reduced problem is available (via a recursive call) and build on that. For instance, if you know the answer for n - 1, how would you use that to compute the answer for n?
Once you've identified those, you are then ready to define and code your recursive method(s).
(I should point out that the n that I'm using here is not necessarily the i you used in your equation. It might make more sense to use the number of terms in the equation as n, or perhaps the number of elements on either side of the middle term. The creative part of recursive problem-solving—and also often the most difficult—is coming up with the right problem representation.)

Recursion or Looping [duplicate]

This question already has answers here:
Recursion or iteration?
(14 answers)
Closed 2 years ago.
I have this method that calculates some statistics:
public void calculateAverage(int hour){
if (hour != 20) {
int data =0;
int times = 0;
for (CallQueue cq : queues) {
data += cq.getCallsByTime().get(hour);
times++;
}
averageData.add((double)data/times);
calculateAverage(hour + 1);
}
}
Now I am very proud that I have created a recursive method but I know that this could have been solved with a loop.
My question is: is it better to solve these kind of problems recursive or with a loop?
Recursion in general
In general, a recursion would be more expensive, because the stack has to be modified with copies of variables for each time the function recurses.
A set of addresses & states need to be saved, so that the recursive procedure can return to the right state after that particular run.
Iteration would be better if possible. Recursion, when iteration just won't cut it, or will result in a lot more complicated code.
Code Maintenance
From a maintenance perspective, debugging iterative code is a lot easier than recursive procedures as it is relatively easier to understand what the state is at any particular iteration, as compared to thinking about a particular recursion.
Your code
The procedure calls itself, but each run has nothing to do with the results of the previous run. Each run being independent, is usually the biggest give-away, that recursion there might not be necessary.
In my opinion, calculateAverage(hour + 1); should be moved outside the function, as it would also be clearer to someone reading your code. that each call is independent.
In Java, C, and Python, recursion is fairly expensive compared to iteration (in general) because it requires the allocation of a new stack frame. In some C compilers, one can use a compiler flag to eliminate this overhead, which transforms certain types of recursion (actually, certain types of tail calls) into jumps instead of function calls. (source)
For this particular problem there isn't too much of a runtime difference. I personally would rather use iteration, I think it would be more simple and easier to understand, but to each his own I suppose.
now some recursive functions(like recursive Fibonacci numbers for example) should be done by iteration instead, simply because they can have exponential growth.
generally, I don't use recursion unless It would make my problem actually easier to understand.
You should investigate the perimeter circumstances. For big recursions stack might get overflow, thats +1 for loops.
I'm not sure which one runs faster but that is relatively easy to measure, taking JIT and other stuff into considerations.
Code maintenance aspect: it is much easier for the most of us to understand and fix loops than recursion. Developers time is usually more important than minor performance differences.
It depends on the context. For example if I have a tree of Composite objects (in SWT) and you wish to traverse them the easiest way is to use recursion like this:
private boolean checkControlParent(Composite comp) {
boolean ret = false;
if (comp != null) {
if (this.equals(comp)) {
ret = true;
} else {
ret = checkControlParent(comp.getParent());
}
}
return ret;
}
otherwise if performance is important be advised that recursive calls are slower in most cases than simple loops because of the function/method call overhead.
So the main thing is that if you need to iterate through objects where recursion is a natural solution and you don't risk a StackOverflowError go ahead and use recursion. Otherwise you'll probably better off with a loop.
One more thing: recursive methods are sometimes tend to be harder to read, understand and debug.

Getting the number of the order of the function in a recursive call

What is the easiest way to retrieve the order of the function in a recursive call. For instance, if we have a recursive function, it keeps calling itself until it finds the base case, and then it returns one function at a time. The first function returning is of order 0, the second is of order 1, and so on...What is an easy way to retrieve the order information? Say for instance, when it is the function of order three, I would like to do something special.
Edit: I want the function at the top of the stack to be zero.
Edit2: The problem I am trying to solve is to return the nth element of the in order traversal of a binary tree.
If you are starting with a recursive function that looks like this
void recursive(int p1, String p2, long p3) {
...
if (someCondition) {
recursive(nextP1, nextP2, nextP3);
}
}
change it to this:
void recursive(int p1, String p2, long p3, int level) {
...
if (someCondition) {
recursive(nextP1, nextP2, nextP3, level+1);
}
}
Now Start off the level at zero by calling
recursive(initialP1, initialP2, initialP3, 0);
level will indicate the number of invocation of recursive above you.
EDIT : (zero-at-the-top)
You can also transform the function to return its level to implement the "zero at the top" strategy:
int recursive(int p1, String p2, long p3) {
if (baseCase) {
return 0;
}
...
int level = 0;
if (someCondition) {
level = 1+recursive(nextP1, nextP2, nextP3);
}
return level;
}
Note that in this case you cannot find your level until after the last recursive invocation has returned.
The case dasblink has offered you covers the opposite of what you suggested implementation-wise because the level counter rises (increments) as you go deeper in the recursion.
If you want it to decrease as you go deeper in the recursion that would imply that you know the exact recursion depth beforehand.
In most cases if you know the exact recursion depth you won't be using recursion, you'll be using a loop (for, while, repeat/until etc.). In fact using recursion in such a case is less optimal because of the recursion stack that gets allocated (higher memory consumption) and loops are much more efficient.
If the level 0 should be the last "nested call", then it is in general
undecidable problem similar to the halting problem, because you can't
just say "after 3 more nested calls, the function will return a
value". It is possible to look ahead only by simulating the
computation of the particular function.
If the level 0 should be the first call, then it is quite simple and you can use the level as a param of the method and increment it.
btw, interesting problem, see http://en.wikipedia.org/wiki/Halting_problem

Categories

Resources