How to ignore StackOverFlow error in Java? [closed] - java

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I know why it gives the error, I don't want to correct it I want the system to ignore it and keep running.
I know that the recursion is not infinite and I need to know when it will stop although I am sure it will be in a very large number and after a good while of execution.
Thankssss.
public static int fun1(int begin, int end, int cont) {
if (begin >= end) {
return 1;
}
cont += fun1(begin, (begin + end) / 2, cont);
cont += fun1(begin + (end - begin) / 4, begin + 3 * (end - begin) / 4, cont);
cont += fun1((begin + end) / 2, end, cont);
return cont;
}

I know that the recursion is not infinite
You "know" a falsehood.
public static int fun1(int begin, int end, int cont) {
if (begin >= end) {
return 1;
}
cont += fun1(begin, (begin + end) / 2, cont);
cont += fun1(begin + (end - begin) / 4, begin + 3 * (end - begin) / 4, cont);
cont += fun1((begin + end) / 2, end, cont);
return cont;
}
Consider what happens if we call fun1(0, 1, 0).
Is begin >= end? No; begin == 0 and end == 1. So we recurse.
What are the arguments for our recursive calls? (begin + end) / 2 is equal to (0 + 1) / 2 is equal to 1 / 2 is equal to 0, with integer division. So the first recursive call is fun1(0, 0, 0).
But the last recursive call is fun1(0, 1, 0). Wait. That looks familiar, yeah? (Never mind the middle one; we have already shown a fault.)

#Karl's answer explains why your function is actually infinitely recursive.
But you asked:
How to ignore StackOverFlow error in Java?
You cannot simply ignore it. If you do that, the program crashes (or a child thread dies, or something) and you don't get an answer.
You could do this:
Integer result = null;
try {
result = fun1(x, y, z);
} catch (StackOverflowError e) {
// We are ignoring this
}
if (result == null) {
System.out.println("cannot compute fun1(x,y,z)");
} else {
System.out.println("fun1(x,y,z) is " + result);
}
But when you look at this, we are not really ignoring the exception. We are catching it and (ultimately) dealing with it as a special case.
Note that you can get a StackOverflowError even in cases where the recursion is not infinite. For example, if I was to add two numbers using recursion:
public int add(int a, int b):
if (a < 0 || b < 0) {
throw new IllegalArgumentException("negative");
else if (a == 0) {
return b;
} else
return add(a - 1, b + 1);
}
Since Java (typically) doesn't do tail-call optimization, large enough arguments will give a StackOverflowError.
So what it the solution to StackOverflowErrors in cases where the function is not infinitely recursive?
One approach would be to use a larger thread stack size. This could be done by using the -Xss<value> option to set the default stacksize for the JVM. Alternatively, you can supply a stack size via the Thread constructor when creating a new thread. However, the maximum practical thread stack size is limited by the amount of available memory, and potentially by JVM, OS and hardware architectural limits.
A second approach is to translate the recursive function into an iterative form. But note that if you simply simulate the recursive calls using a stack implemented in software, you have to deal with the possibility that that data structure gets too big.
A third approach is to try and find an algebraic solution; i.e. turn this into a mathematical problem.
But note that there are some cases where none of the above will work. For example, consider the Ackermann function.

Related

How can I solve this problem with recursion in Java?

public static int[] generateNumbers(int start, int end) {
// case for empty array
if (start > end) {
int returnEmptyArray[] = {};
return returnEmptyArray;
}
// setting size of the result array
if (start < 0) {
int sizeOfArray = end - start - 1;
int result[] = new int[sizeOfArray];
}
// setting size of the result array
if (start > 0) {
int sizeOfArray = end - start;
int result[] = new int[sizeOfArray];
return generateNumbers(start, end, 0, result);
}
return null;
}
// helping method for recursion
public static int[] generateNumbers(int start, int end, int i, int[] result) {
i = start;
if (i < end) {
result[i] = i;
i++;
}
return generateNumbers(start, end, ++i, result);
}
Hi everybody!
I have tried everything I could imagine to solve this problem.
This program should count upwards recursively from start to end and negative numbers should be included as well. In the end, the result should be put into an integer array.
Examples:
start: 2, end: 5 --> result = {2, 3, 4, 5}
start: -4, end: 3 --> result = {-4, -3, -2, -1, 0, 1, 2, 3}
I would be really thankful for a code snippet and an explanation or at least an approach how I can solve this problem.
There are some quite odd parts in your code.
For example this:
if (start < 0) {
int sizeOfArray = end - start - 1;
int result[] = new int[sizeOfArray];
}
is pointless, you are creating local variables in if condition and never use them.
Your calculation of the sizeOfArray is wrong, it should be end - start + 1, also, there is no reason to check whether start is positive or negative, ditch it all. Then, remove return null, it's a dead code.
For your subroutine function, you can't just write into array on the same index as the number you are about to write, you will get ArrayIndexOutOfBoundsException. For example if your start is -4, you will basically (in the first call) attempt to do result[-4] = -4, which is obviously nonsence.
Better solution would be to hold index value in i (starting from 0) and adding this value to start: result[i] = start + i.
Also, the ++i call is wrong, as you call i++ right before it, so you are actually increasing i by 2 instead of 1.
Your subroutine also has no terminating condition - it can never end. Try to put it in format:
if(...) {
...
return generateNumbers(...);
}
return result;
Btw, you will obviously need to edit your condition after changing what i does.
Instead of giving you a solution, I'll go through the reasoning how to find the solution.
[ We all fully understand that creating such an array of integers this way is meant as an exercise in recursive thinking, not to be done this way in production-quality software. ]
The main two questions for recursion are always:
For a given task, like generateNumbers(3,7), how can I solve it by re-using the results of a "simpler" task of the same type?
What is a task so simple that I want to solve it directly? And I should choose a case where I'll surely arrive when applying my simplification strategy from question 1.
One possible answer is (there are other possibilities):
If I know the result of generateNumbers(3,6), I just have to append the 7 at the end, and then I got it. Generalized: Solving the question generateNumbers(start,end-1), and then appending end.
If start is greater than end, the result is an empty array.
Implementing that is straightforward, with one quirk: appending something to an array isn't easy in Java. You can:
Make the recursion more complicated, by first creating an array long enough to hold the final result, and in the recursive calls keep track of the position where to append the new number.
Use the List data type instead of an array (if your course has covered that). Appending to a List is easy.
Write an int[] append(int[] arraySoFar, int newValue) method, thus making the "append" step in the recursion easy. The method has to create a new array, one longer than the input, copy the input there, and insert the new value at the end.
Just to show you that there can be many different ways of using resursion for your problem, here are a few other approaches:
Instead of reducing the end by one, and then appending the end number, you can increase the start by one and prepend the start number.
For solving generateNumbers(3,7), you can find some number in the middle, e.g. 5, and solve by appending generateNumbers(3,5) and generateNumbers(6,7), meaning that you create the result of one generateNumbers() call by cleverly combining the results of two recursive calls.
public static int[] generateNumbers(int start, int end) {
int length = end - start + 1;
if(length <= 0) {
// throw an exception
}
int[] numbers = new int[length];
generateNumbers(start, end, 0, numbers);
return numbers;
}
public static void generateNumbers(int start, int end, int index, int[] numbers) {
if(start > end) {
return;
}
numbers[index] = start;
generateNumbers(start + 1, end, index + 1, numbers);
}

Evaluation order in Java

So I have this code for the Fibonacci sequence:
int fibonacci(int i, int[] memo) {
if (i == 0 || i == 1) return i;
if (memo[i] == 0) {
memo[i] = fibonacci(i - 1, memo) + fibonacci(i - 2, memo);
}
return(memo[i]);
}
My question is: fibonacci(i-1, memo) will always be evaluated before fibonacci(i-2, memo) correct?
Correct, from left to right.
First you will completely traverse the recursion with the left argument fibonacci(i - 1, memo) after that, when it moves the recursion tree up again, each time the right argument will get computed, again with a full recursive tree.
A quick search yield this image illustrating the process:
Note that many values are often computed multiple times. Your current approach tries to optimize this by caching results inside an array memo.

Learning Java - Do not fully understand how this sequence is calculated (Fibonacci) in for loop [duplicate]

This question already has answers here:
Java recursive Fibonacci sequence
(37 answers)
Closed 8 years ago.
I am learning Java and I have this code from the internet and running it in Eclipse:
public class Fibonacci {
public static void main (String [] args) {
for (int counter = 0; counter <= 3; counter++){
System.out.printf("Fibonacci of %d is: %d\n", counter, fibonacci(counter));
}
public static long fibonacci(long number) {
if ((number == 0) || (number == 1))
return number;
else
return fibonacci(number - 1) + fibonacci(number - 2);
}
}
I've tried to understand it but cannot get it. So I run through the code and counter gets passed in through the fibonacci method. As counter starts at 0 and this is what gets passed first, then 1 and I understand the method passes back 0 and then 1.
When it reaches 2: it will return 2-1 + 2-2 = 2 and it does return this.
When it reaches 3: it will return 3-1 + 3-2 = 3 but it does not return 3 it returns 2.
Please can someone explain to me why as I cannot figure this out?
Thanks
First, I have to tell you that this recursive version has a dramatic exponential cost. Once you understand how it works, my advice for you would be to learn about tail recursivity, write a tail-recursive solution, an iterative solution, and compare them to your current method for high values of "number".
Then, your function basically uses the mathematical definition of the Fibonacci sequence :
f0 = 1, f1 = 1, fn = fn-1 + fn-2 for all n >= 2
For example if we call fibonacci(3), this will return fibonacci(2) + fibonacci(1). fibonacci(2) will be executed first and will return fibonacci(1) + fibonnacci(0). Then fibonacci(1) will return immediately 1 since it is a terminal case. It happens the same thing with fibonnacci(0), so now we have computed fibonnacci(2) = 1 + 0 = 1. Let's go back to fibonacci(3) which has been partially evaluated at this point : 1 + fibonnacci(1). We just have to compute fibonnacci(1) and we can finally return 1 + 1 = 2.
Even in this little example, you can see that we evaluated twice fibonacci(1), that is why this version is so slow, it computes many times the same values of the sequence, and it gets worth when "number" is high.

Recursive definition solution

im studying for my final exam from the text book. I need an answer for this question since i couldn't solve it.
1)Write a recursive definition of the function multiply(int a, int b) that takes two integers and return the result of their multiplication.
I answered:
Multiply(a, b) :
0 - if a or b is equal to zero. (I got -1 here. Reason written: only 1)
a * b - (I didn't know what to write here)
2)
Write a recursive method that takes a linked list of integers and returns the sum of it's elements.
My solution was:
int sumList(Node<Integer> list) {
int temp = list.getInfo();
if(temp == null) {
return 0;
} else {
return temp + sumList(temp.getNext);
}
}
I fixed it, i think:
public int sumList(Node<Integer> list) {
Node<Integer> temp = list;
if(temp == null) {
return 0;
} else {
return temp.getInfo() + sumList(temp.getNext());
}
}
Is the solution for question 2 right?
Since this is for exam preparation, I don't want to give you the code for doing this. Instead I will give you some ideas.
For the question no 1. Since multiplication is repeated summation, you can use that as the base for recursion here.
If you want to find 3 * 4, use recursion to calculate and return 4 + 4 + 4.
In other words, you can see a pattern emerge below.
4 * 3 = 4 + (4 * 2)
4 * 3 = 4 + 4 + (4 * 1)
To get a working recursive solution you need a base case, for example a == 0, and then work yourself down towards the base case by recursively calling yourself.
The solution for question 1 could be something along the lines of this, that decreases the a argument until it reaches 0:
int multiply(int a, int b) {
if (a == 0 || b == 0) {
return 0;
}
return b + multiply(a - 1, b);
}
For example, multiply(2, 5) would become 5 + multiply(1, 5) -> 5 + 5 + multiply(0, 5) -> 5 + 5 + 0.
Note that this particular solution doesn't work for negative numbers, but you get the idea. You should be able to easily add support for that yourself.
A) well, you really need to reread that chapter on recursion.
The mathematical principle is this:
http://en.wikipedia.org/wiki/Mathematical_induction
and the Wikipedia article will step you through a much more complicated task.
B) No, it won't compile at all. There are multiple syntax errors.
Try using a Java compiler for excersising your programming skills.

Two different way of recursion

I calculate fibonachi row in two different ways. Why fib1 executes much longer then fib2?
public class RecursionTest {
#Test
public void fib1() {
long t = System.currentTimeMillis();
long fib = fib1(47);
System.out.println(fib + " Completed fib1 in:" + (System.currentTimeMillis() - t));
t = System.currentTimeMillis();
fib = fib2(47);
System.out.println(fib + " Completed fib2 in:" + (System.currentTimeMillis() - t));
}
long fib1(int n) {
if (n == 0 || n == 1) {
return n;
} else {
return fib1(n - 1) + fib1(n - 2);
}
}
long fib2(int n) {
return n == 0 ? 0 : fib2x(n, 0, 1);
}
long fib2x(int n, long p0, long p1) {
return n == 1 ? p1 : fib2x(n - 1, p1, p0 + p1);
}
}
The output:
2971215073 Completed fib1 in:17414
2971215073 Completed fib2 in:0
Because both algorithms work entirely different. Let me show you this with fib(5).
if you call fib1(5), it internally calls fib1(4) und fib1(3), lets visualize that with a tree:
fib(5)
/ \
fib(4) fib(3)
now, fib(4) internally calls fib(3) and fib(2).
So now we have this:
fib(5)
/ \
fib(4) fib(3)
/ \ / \
fib(3) fib(2) fib(2) fib(1)
I think by now it is very obvious where this is going, you should be able to fill in the rest.
edit: Another thing you should notice here is, that it actually has to performe the same caclculation multiple times. In this picture, fib(2) und fib(3) are both called multiple times. And this gets worse if the starting number is bigger./edit
Now, let's take a look at fib2(5). It you call it with 0, it returns 0. Otherwise, it calls fib2x(n, 0,1)
So, we have a call to fib2x(5,0,1). fib2x(n, 0,1) now internally calls fib2x(n-1, p1, p0+p1) and so on.
So, lets see:
fib2x(5, 0,1) => fib2x(4, 1,1) => fib2x(3, 1, 2) => fib2x(2, 2, 3) => fib2x(1, 3, 5)
by then, it has reached the return condition and returns 5.
So, your algorithms work entirely different. The first one works recursively and from the top to the bottom.
The second one starts at 1 and works his way up. Actually, it is more iterative then recursive (it was probably written recursive to throw you off). It keeps the already calculated values instead of discarding them and therefore needs to invoke far less calculations.
The reason is two algorithms have different runtime complexities:
fib1 is in Ο(2n)
fib2 is in Ο(n)
Ultimately, it's because fib2 only uses tail end recursion. It only makes one recursive call at the end. Thus there isn't any "branching" associated with the recursion and leads to a linear time solution. The fact that it's a tail call also leads to certain compiler/VM optimizations where the recursion can be converted into an iterative procedure with lower overhead.
fib1 uses another recursive call in addition to the tail-call which causes the running time to be exponential.
fib1 is an algorithm with O(2^n) runtime. fib2 is an algorithm with O(n) runtime.
The reason for this is pretty cool -- it's a technique called memoization. The work the program does is saved at each step, avoiding any extraneous calculation.
You can see it happen by unrolling the loop a couple more steps:
long fib2(int n) {
return n == 0 ? 0 : fib2x(n, 0, 1);
}
long fib2x(int n, long p0, long p1) {
return n == 1 ? p1 : fib2xy(n - 1, 1, 1);
}
long fib2xy(int n, long p0, long p1) {
return n == 1 ? p1 : fib2xyz(n - 1, 1, 2);
}
long fib2xyz(int n, long p0, long p1) {
return n == 1 ? p1 : fib2xyz(n - 1, p1, p0 + p1);
}
You can unroll this loop to any arbitrary number in the fibonacci sequence; each step builds on the calculation stored previously in the stack until n is depleted. This is in contrast to the first algorithm, which must redo this work at every step. Nifty!

Categories