How to fix a java.lang.StackOverflowError [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
My teacher makes us do these error fixing assignments, and I just can't fix this one. That's why I came here. I want to ask for one favor and a few questions
Questions: What does the error message mean in detail(I just want to know for my own curiosity), Why does it occur specifically using my code, How can I fix it
Favor: Can u please fix my code, Sorry if this seems like a way to get an answer but I'm a bit lost.
Here's the code
public class Recursion
{
public static void indifferent( int x, int y )
{
System.out.print( x );
indifferent( x - 1, y + 2 );
System.out.print( y );
}
}
public class RecursionDriver//-the driver class
{
public static void main( String [] args )
{
Recursion.indifferent( 7, -1 );
}
}

If you examine the code it should be obvious that it can never terminate. Every call to indifferent makes another call to indifferent. Unconditionally.
The StackOverflowError happens because the nested calls have gotten too deep. Java method calls use a stack to hold local variables (and the return address, and other stuff). The stack has a fixed size. If you have too many nested calls, the stack overflows.
How to fix it? Rewrite the code to do what it is currently doing, but without using recursion.
But first you need to understand what it is doing. How do you do that? Well ... basically ... you read the code.
Well I'm not completely sure what indifferent means because this is what my teacher told us to put as the name for the class(she said its meaningless and told us to ignore it)
Yup. Ignore the name, and read what the code actually does. If you can't figure it out ... then "hand execute" it using a pencil and paper.

In recursion you try to divide your problem in sub problems and try to compute the result. Hence, in recursion you always need to have a base case. Base case in the final depth of your recursion. Once you reach the base case you start coming out of the recursion and get you final answer.
In your code:
public static void indifferent( int x, int y )
{
System.out.print( x );
indifferent( x - 1, y + 2 );
System.out.print( y );
}
You do not have a base case, do your code just keeps going deep in recursion.
public static void indifferent( int x, int y )
{
if(x == 1) //example of a base case
return;
System.out.print( x );
indifferent( x - 1, y + 2 );
System.out.print( y );
}

Related

Needing help understanding logic in "Head First Java" [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have recently started programming in Java for the first time (just as a hobby), and at the moment Im working with a book "Head First Java" that is very good, but I'm really struggling with understanding the exercises.
Like this for example:
class Output {
void go() {
int y = 7;
for(int x = 1; x < 8; x++) {
y++; // is y now 8?
if(x >4) {
System.out.println(++y + " "); // does this make y = 9?
}
if(y > 14) {
System.out.println(" x = " + x);
break; // how does the break key word affect the rest of the loop?
}
}
}
public static void main(String[] args) {
Output o = new Output();
o.go();
}
}
Can someone please explain to me what goes on in this code?
Variable y must be 15, because you increased it's value many times with the for loop.
++y increases it's value by 1. i++ and ++i are very similar but not exactly the same. Both increment the number, but ++i increments the number before the current expression is evaluted, whereas i++ increments the number after the expression is evaluated.
break simply exists from the loop.

Is it wise to "exploit" java call-by-value [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Consider the following siutation. A user can enter something like
30D, 90D, 180D, 360D, 1M, 3M, 6M, 12M, 1Y
(D=day, M=month, Y=year).
I want to compute the number of months with the following two methods.
private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
int periodInMonths = lengthOfPeriod;
if ("D".equals(unitOfPeriod)) {
periodInMonths = lengthOfPeriod / 30;
} else if ("Y".equals(unitOfPeriod)) {
periodInMonths = lengthOfPeriod * 12;
}
return periodInMonths;
}
private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
if ("D".equals(unitOfPeriod)) {
lengthOfPeriod = lengthOfPeriod / 30;
} else if ("Y".equals(unitOfPeriod)) {
lengthOfPeriod = lengthOfPeriod * 12;
}
return lengthOfPeriod;
}
Because java works with call-by-value with a reference passed as a value lengthOfPeriod won't change outside of the method. I am not sure what is more appropriate to use.
I know that this method could be refactored by using an enum Periods or something like that. But let's not discuss this here.
Assigning to method parameters is not a good idea (and they should've been made final by default IMHO). If you really want to avoid the extra variable (not that it really makes a difference), you can put returns in your if clauses.
But don't use parameters as "automatic local variables". It can cause hard to see bugs and doesn't make your code any more performant.
The only difference is that you use an own variable int periodInMonths = lengthOfPeriod; in the first method. But this isn't necessary!
You can use the second one.. It does what it should!
int lengthOfPeriodInMonths = getLengthOfPeriodInMonths(lengthOfPeriod, unitOfPeriod);
and you have the calculated int outside of the method stored in lengthOfPeriodInMonths
P.S.: This call
lengthOfPeriod = lengthOfPeriod / 30;
is equivalent to
lengthOfPeriod = new Integer(lengthOfPeriod / 30);
(look "auto-boxing" in Java).
So, as you said, Java uses call-bay-value. The variable lengthOfPeriod gets assigned a new refernece in this call. So this calculation would be lost outside the method! That's why you must return the newly computed value!
First advice: never ever modify the method parameters. They should reflect the value passed by the user of the method at all times.
Second advice: if someone advises you to never do something, especially if he or she uses the phrase "never ever", take his or her advice with a grain of salt. There are no rules without exceptions (never ever ;-). Such rules are great rules of thumb, but always use your own judgement. Choose the solution which you think is clearer. I know of some situations where I found modifying method parameters was more readable than the alternative.
For example, sometimes you might want to allow the user of the method to pass null to the method, but then replace it with some default value. I find the following method
public void doSomething(String s) {
if (s == null) s = "";
System.out.println(s);
}
much clearer than introducing a local variable just to include the default value:
public void doSomething(final String s) {
String sOrEmpty = s == null ? "" : s;
System.out.println(sOrEmpty);
}

Repeat String Recursively [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is homework. I get the logic but i got stuck on the code. I've done it with normally way and it takes 1 week to get the code. I need to get repeat string with recursive way in Java.
This is my code :
static String repeatString (final int n, final String[] syllables, final String currentWord) {
if (n == 0) {
System.out.println(currentWord);
} else {
for (int i = 0; i < syllables.length; i++) {
repeatString(n - 1, syllables, currentWord + syllables[i]);
}
}
return "";
}
if i call in main method like
String[] str = {"a", "b"};
repeatString(1, str, " ");
then i get output (a,b) if i change to
repeatString(2,str," ");
then i get output ( aa,ab,ba,bb) if i change to
repeatString(3,str," ");
then i get output (aaa,aab,aba,abb,baa,bab,bba,bbb) and so on.
So basically it is like 2 to the power to n. If n=1, i got 2, if n=3, i got 8, and so on.
I would be grateful if someone can help me to get this code in recursive way.
Any help is much appreciated.
The method you have there is recursive already. Being recursive does NOT mean it should have no for loops. A recursive method in cheap words means the method calls itself, which yours does.

Obtain the largest number in an array of numbers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is my first time doing java and I am am trying to get the largest number from an array of x numbers using a method called bigNum(). Can anyone tell me why this doesn't work?
class project3
{
public static void main(String args[])
{
int total =0;
int b;
System.out.println("How many numbers do you want in the array");
int maxItems = EasyIn.getInt();
int[] numbers = new int[maxItems];
for (int i=0; i < maxItems; i++)
{
b = EasyIn.getInt();
}
bigNum(b);
}
public static void bigNum(int maxItems)
{
for (int i = 1; i >= maxItems; i++)
{
if (bigNum(b) >= maxItems)
bigNum(b) = maxItems;
}
return bigNum(b);
}
}
You're probably getting compiler errors at this point due to unmatched braces. You want your program to have matched braces, and you also want to avoid having methods inside of other methods.
You want to have something that has the following form
class project3
{
public static void main(String args[])
{
...
}
public static int bigNum(int maxItems[])
{
...
return someInt;
}
}
// capital letter for the class (convention)
public class Project3 {
public static void main(String args[]) {
//int total = 0; // you never used this number
System.out.println("How many numbers do you want in the array");
int maxItems = EasyIn.getInt();
int[] numbers = new int[maxItems];
for(int i = 0; i < maxItems; ++i) {
int newNumber = EasyIn.getInt();
/* you want to put the numbers into an array,
so don't call "bigNum" but put them there: */
numbers[i] = newNumber;
}
// now find the big number:
int bigNumber = bigNum(numbers);
System.out.println("The biggest number: " + bigNumber);
}
// first: change the return type to get the biggest number
// second: pass the reference to the array, not a single number
// public static void bigNum(int maxItems) {
public static int bigNum(int[] items) {
// create big number, assume it's very small:
int bigNumber = Integer.MIN_VALUE;
// this for loop will never run, change it a bit:
//for(int i = 1; i >= maxItems; i++) {
for(int i = 0; i < items.length; i++) {
// your idea is correct, but you can not use the
// method here, see explanations below
// Also don't check for the number of Items, but for
if(items[i] > bigNumber) {
bigNumber = items[i];
}
}
return bigNumber;
}
}
Explanations and further readings
Class name: Java has lots of different naming conventions, but the most common rules are: ClassNames/Types in CamelCase with a Capital at the beginning, variableNames following a similar convention but with a leading small letter. This makes it much easier to read code.
Indentation: Try to use a more consistent indentation. Also supports readability. Actually some other programming languages even rely on correct indentation.
Try to understand what variables and what methods are and how to use them (and return from them, you can not assign values to a method in Java. While you read the latter tutorial focus on return types and how to call methods correctly, you can not return an int when your method is of type void. Also the parameters need to be exactly defined.
Apart from that try to compile your code before you post it. As your code went, it should have thrown lots of compile errors, e.g. bigNum(b) = maxItems; should tell you that the left-hand side of an assignment needs to be a variable. This can help you a lot while tracking down mistakes.
Another error is that for most people EasyIn will not be defined (as it is for me, so the code I posted above might actually not be working, I didn't try). I suppose it's a learning library (we had our AlgoTools back in our first Java lectures). Still it would be nice to tell us what it is and what other imports you use (common mistake when I let my IDE decide my imports for me: java.util.Date and java.sql.Date).
Also try to make clear to yourself what you want to achieve with your program and how. Your algorithm actually looks like you didn't think too much about it: You try to find a biggest number and always check "a big number" against the number of expected items, which then might become "the big number" as well. Or something like that.
Programming is being concise and exact, so make a plan before. If it's too hard for you to think about a solution directly, you can maybe draw it on paper.
And if you then have problems, after compiling, asking your program, asking google, asking stack overflow: provide us with as many details as you can and we will be able to help you without just posting some code.
Good luck!

Formula with Recursion (n+(n-1)+n) error [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need to use recursion to calculate how many medals a player gets for example if I enter 3 the player got 8 medals [Ex1.(3+(3-1)+3)=(3+2+3)=8]/[Ex2.(5+(5-1)+5)=(5+4+5)=14] When I enter 1 on the main method to test it works but when I change a number greater than 1 it crashes and I get red letters as error this is the error I get. I have done about 5 recursion methods already but I'm stuck on this one.
java.lang.StackOverflowError
at RecursiveFunctions.countMedals(RecursiveFunctions.java:87)
public class RecursiveFunctions{
public static int countMedals(int n){
if(n==0){
return 1+(1-1)+1;
}
else{
return countMedals((n)+(n-1)+(n));
}
public static void main(String[] args){
System.out.println("Number of Medals: " + RecursiveFunctions.countMedals(3));
}
}
Try tracing through the function to see what happens:
countMedals(3) returns countMedals(3 + 2 + 3)
countMedals(8) returns countMedals(8 + 7 + 8)
This is going to continually grow, and never hit your base case of 0.
Your formula has no recursive logic. There is no iteration, it's just a simple math equation.
public static int countMedals(int n){ return 3*n - 1;}
You recursive method has no endpoint in the recursive calls.
You call:
countMedals((n)+(n-1)+(n))
If n is 2, this expression evaluates:
countMedals((2)+(2-1)+(2)) -> countMedals(5)
And this is:
countMedals((5)+(5-1)+(5)) -> countMedals(14)
And so on... You never stop. So you stack is full, and Java crashes.
From your code, it looks like you will never reach the case where n == 0. This is why you are entering infinite recursion.
Each time you call your function with n + (n - 1) + n, which is essentially 3n - 1. So what you have is f(n) = 3n - 1, and you're passing the result of that into the function itself. Now f(n) = 0 only when n = 1 / 3. Can you see any way where n can ever be 1 / 3?
Also, try plotting this function on a graph. What do you see happening to the y values as you keep increasing x (basically n in this case)?
I don't see how you can apply recursion like this. To compute f(n) you need to compute f(3n-1), for which you need to compute f(f(3n-1)), etc. It never terminates, so you get a stack overflow.
In fact I don't know why you are recursing at all, if f(3) and f(5) both = 3n-1. Evidently you haven't understood your problem correctly.

Categories

Resources