Recursive function throws java.lang.StackOverflowError - java

I get the error java.lang.StackOverflowError when I try to run my code:
public class calc {
public static void main(String[] args){
double zahl = 847362;
System.out.println( wannawoerk(zahl) );
}
public static double wannawoerk(double zahl){
if (zahl == 1)
return 1;
else
return wannawoerk(zahl - 1) + zahl;
} }
Is there any workaround for this problem? I have to use a recursive function without for, while, etc.

Repeated subtraction of 1 from zahl will eventually give you 1. (Floating point subtraction by an integer on integers in this range is exact: you'd only get oddities above the 53rd power of 2).
Your problem is that your JVM is probably not going to allow you that many recursive calls.
A stack depth approaching one million is really not going to end well!

If you're required to use recursion, you could increase memory available for stack: java -Xss256m YourClass - sets stack to 256MB max.
In real world, you'd most probably use a while loop for this. Or, in this case, compute it right away (you don't need recursion for the thing you are computing), but I guess that's not the point.

The stack is not unlimited and Java doesn't have tail call optimisation. The simplest solution is to have the method
return zahl * (zahl + 1) / 2;
Ideally you wouldn't use double instead you would write
public static long sumUpTo(int n) {
return n * (n + 1L) / 2;
}
To make any sane optimisation you need a more realistic method.

This example of yours is very also illustrated in this comment! along with a few other very detailed explanations of this issue, why it happens and how to handle it.

Related

Converting a binary string to integer using a basic mathematical operator

Main:
public class Main{
public static void main(String[] args){
System.out.println(Convert.BtoI("10001"));
System.out.println(Convert.BtoI("101010101"));
}
}
Class:
public class Convert{
public static int BtoI(String num){
Integer i= Integer.parseInt(num,2);
return i;
}
}
So I was working on converters, I was struggling as I am new to java and my friend suggested using integer method, which works. However, which method would be most efficient to convert using the basic operators (e.g. logical, arithmetic etc.)
.... my friend suggested using integer method, which works.
Correct:
it works, and
it is the best way.
However, which method would be most efficient to convert using the basic operators (e.g. logical, arithmetic etc.)
If you are new to Java, you should not be obsessing over the efficiency of your code. You don't have the intuition.
You probably shouldn't optimize this it even if you are experienced. In most cases, small scale efficiencies are irrelevant, and you are better off using a profiler to validate your intuition about what is important before you start to optimize.
Even if this is a performance hotspot in your application, the Integer.parseint code has (no doubt) already been well optimized. There is little chance that you could do significantly better using "primitive" operations. (Under the hood, the methods will most likely already be doing the same thing as you would be doing.)
If you are just asking this because you are curious, take a look at the source code for the Integer class.
If you want to use basic arithmetic to convert binary numbers to integers then you can replace the BtoI() method within the class Convert with the following code.
public static int BtoI(String num){
int number = 0; // declare the number to store the result
int power = 0; // declare power variable
// loop from end to start of the binary number
for(int i = num.length()-1; i >= 0; i--)
{
// check if the number encountered is 1
/// if yes then do 2^Power and add to the result
if(num.charAt(i) == '1')
number += Math.pow(2, power);
// increment the power to use in next iteration
power++;
}
// return the number
return number;
}
Normal calculation is performed in above code to get the result. e.g.
101 => 1*2^2 + 0 + 1*2^0 = 5

How to transfer an outside recursion program into a non-recursive form (using stack not CPS)?

there are many questions about how to convert recursive to non-recursive, and I also can convert some recursive programs to non-recursive form
note: I use an generalized way (user defined Stack), because I think it is easy to understand, and I use Java, so can not use GOTO keyword.
Things don't always go so well, when I meet the Backtracking, I am stuck. for example, The subset problem. and my code is here: recursive call with loop
when i use user defined Stack to turn it to non-recursive form. I do not know how to deal with the loop (in the loop existing recursive call).
I googled found that there is many methods such as CPS. and I know there is an iterative template of subset problem. but i only want to use user defined Stack to solve.
Can someone provide some clues to turn this kind of recursive(recursive with loop) to non-recursive form(by using user defined Stack, not CPS etc..) ?
here is my code recursive to non-recusive(Inorder-Traversal), because of there is no loop with recursive call, so i can easily do it. also when recursive program with a return value, I can use a reference and pass it to the function as a param. from the code, I use the Stack to simulated the recursive call, and use "state" variable to the next call point(because java does not allow using GOTO).
The following is the information I have collected. It seems that all of them does not satisfy the question I mentioned(some use goto that java not allowed, some is very simple recursive means that no nested recursive call or recursive call with loop ).
1 Old Dominion University
2 codeproject
----------------------------------Split Line--------------------------------------
Thks u all. after when I post the question... It took me all night to figure it out. here is my solution: non-recursive subset problem solution, and the comment of the code is my idea.
To sum up. what i stuck before is how to deal with the foo-loop, actually, we can just simply ignore it. because we are using loop+stack, we can do a simple judgment on whether to meet the conditions.
On your stack, have you thought about pushing i (the iteration variable)?
By doing this, when you pop this value, you know at which iteration of the loop you were before you pushed on the stack and therefore, you can iterate to the next i and continue your algorithm.
Non-negative numbers only for simplicity. (Also no IntFunction.)
The power function, as defined here, is a very simple case.
int power(int x, int exponent) {
if (exponent == 0) {
return 1;
} else if (exponent % 2 == 0) {
int y = power(x, exponent /2);
return y * y;
} else {
return x * power(x, exponent - 1);
}
}
Now the stack is there to do in the reverse order to a partial result, what you did in recursion with the result.
int power(final int x, int exponent) {
Stack<Function<Integer, Integer>> opStack = new Stack<>();
final Function<Integer, Integer> square = n -> n * n;
final Function<Integer, Integer> multiply = n -> x * n;
while (exponent > 0) {
if (exponent % 2 == 0) {
exponent /= 2;
opStack.push(square);
} else {
--exponent;
opStack.push(multiply);
}
}
int result = 1;
while (!opStack.isEmpty()) {
result = opStack.pop().apply(result);
}
return result;
}
An alternative would be to "encode" the two branches of if-else (odd/even exponent) by a boolean:
int power(final int x, int exponent) {
BooleanStack stack = new BooleanStack<>();
while (exponent > 0) {
boolean even = exponent % 2 == 0;
stack.push(even);
if (even) {
exponent /= 2;
} else {
--exponent;
}
}
int result = 1;
while (!stack.isEmpty()) {
result *= stack.pop() ? result : x;
}
return result;
}
So one has to distinghuish:
what one does to prepare the recursive arguments
what one does with the partial results of the recursive calls
how one can merge/handle several recursive calls in the function
exploit nice things, like x being a final constant
Not difficult, puzzling maybe, so have fun.

How should I decorate JSONObject? [duplicate]

What is a StackOverflowError, what causes it, and how should I deal with them?
Parameters and local variables are allocated on the stack (with reference types, the object lives on the heap and a variable in the stack references that object on the heap). The stack typically lives at the upper end of your address space and as it is used up it heads towards the bottom of the address space (i.e. towards zero).
Your process also has a heap, which lives at the bottom end of your process. As you allocate memory, this heap can grow towards the upper end of your address space. As you can see, there is a potential for the heap to "collide" with the stack (a bit like tectonic plates!!!).
The common cause for a stack overflow is a bad recursive call. Typically, this is caused when your recursive functions doesn't have the correct termination condition, so it ends up calling itself forever. Or when the termination condition is fine, it can be caused by requiring too many recursive calls before fulfilling it.
However, with GUI programming, it's possible to generate indirect recursion. For example, your app may be handling paint messages, and, whilst processing them, it may call a function that causes the system to send another paint message. Here you've not explicitly called yourself, but the OS/VM has done it for you.
To deal with them, you'll need to examine your code. If you've got functions that call themselves then check that you've got a terminating condition. If you have, then check that when calling the function you have at least modified one of the arguments, otherwise there'll be no visible change for the recursively called function and the terminating condition is useless. Also mind that your stack space can run out of memory before reaching a valid terminating condition, thus make sure your method can handle input values requiring more recursive calls.
If you've got no obvious recursive functions then check to see if you're calling any library functions that indirectly will cause your function to be called (like the implicit case above).
To describe this, first let us understand how local variables and objects are stored.
Local variable are stored on the stack:
If you looked at the image you should be able to understand how things are working.
When a function call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowError is thrown by the Java Virtual Machine (JVM).
The most common case that can possibly exhaust a Java application’s stack is recursion. In recursion, a method invokes itself during its execution. Recursion is considered as a powerful general-purpose programming technique, but it must be used with caution, to avoid StackOverflowError.
An example of throwing a StackOverflowError is shown below:
StackOverflowErrorExample.java:
public class StackOverflowErrorExample {
public static void recursivePrint(int num) {
System.out.println("Number: " + num);
if (num == 0)
return;
else
recursivePrint(++num);
}
public static void main(String[] args) {
StackOverflowErrorExample.recursivePrint(1);
}
}
In this example, we define a recursive method, called recursivePrint that prints an integer and then, calls itself, with the next successive integer as an argument. The recursion ends until we pass in 0 as a parameter. However, in our example, we passed in the parameter from 1 and its increasing followers, consequently, the recursion will never terminate.
A sample execution, using the -Xss1M flag that specifies the size of the thread stack to equal to 1 MB, is shown below:
Number: 1
Number: 2
Number: 3
...
Number: 6262
Number: 6263
Number: 6264
Number: 6265
Number: 6266
Exception in thread "main" java.lang.StackOverflowError
at java.io.PrintStream.write(PrintStream.java:480)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:4)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
...
Depending on the JVM’s initial configuration, the results may differ, but eventually the StackOverflowError shall be thrown. This example is a very good example of how recursion can cause problems, if not implemented with caution.
How to deal with the StackOverflowError
The simplest solution is to carefully inspect the stack trace and
detect the repeating pattern of line numbers. These line numbers
indicate the code being recursively called. Once you detect these
lines, you must carefully inspect your code and understand why the
recursion never terminates.
If you have verified that the recursion
is implemented correctly, you can increase the stack’s size, in
order to allow a larger number of invocations. Depending on the Java
Virtual Machine (JVM) installed, the default thread stack size may
equal to either 512 KB, or 1 MB. You can increase the thread stack
size using the -Xss flag. This flag can be specified either via the
project’s configuration, or via the command line. The format of the
-Xss argument is:
-Xss<size>[g|G|m|M|k|K]
If you have a function like:
int foo()
{
// more stuff
foo();
}
Then foo() will keep calling itself, getting deeper and deeper, and when the space used to keep track of what functions you're in is filled up, you get the stack overflow error.
Stack overflow means exactly that: a stack overflows. Usually there's a one stack in the program that contains local-scope variables and addresses where to return when execution of a routine ends. That stack tends to be a fixed memory range somewhere in the memory, therefore it's limited how much it can contain values.
If the stack is empty you can't pop, if you do you'll get stack underflow error.
If the stack is full you can't push, if you do you'll get stack overflow error.
So stack overflow appears where you allocate too much into the stack. For instance, in the mentioned recursion.
Some implementations optimize out some forms of recursions. Tail recursion in particular. Tail recursive routines are form of routines where the recursive call appears as a final thing what the routine does. Such routine call gets simply reduced into a jump.
Some implementations go so far as implement their own stacks for recursion, therefore they allow the recursion to continue until the system runs out of memory.
Easiest thing you could try would be to increase your stack size if you can. If you can't do that though, the second best thing would be to look whether there's something that clearly causes the stack overflow. Try it by printing something before and after the call into routine. This helps you to find out the failing routine.
A stack overflow is usually called by nesting function calls too deeply (especially easy when using recursion, i.e. a function that calls itself) or allocating a large amount of memory on the stack where using the heap would be more appropriate.
Like you say, you need to show some code. :-)
A stack overflow error usually happens when your function calls nest too deeply. See the Stack Overflow Code Golf thread for some examples of how this happens (though in the case of that question, the answers intentionally cause stack overflow).
A StackOverflowError is a runtime error in Java.
It is thrown when the amount of call stack memory allocated by the JVM is exceeded.
A common case of a StackOverflowError being thrown, is when the call stack exceeds due to excessive deep or infinite recursion.
Example:
public class Factorial {
public static int factorial(int n){
if(n == 1){
return 1;
}
else{
return n * factorial(n-1);
}
}
public static void main(String[] args){
System.out.println("Main method started");
int result = Factorial.factorial(-1);
System.out.println("Factorial ==>"+result);
System.out.println("Main method ended");
}
}
Stack trace:
Main method started
Exception in thread "main" java.lang.StackOverflowError
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
In the above case, it can be avoided by doing programmatic changes.
But if the program logic is correct and it still occurs then your stack size needs to be increased.
StackOverflowError is to the stack as OutOfMemoryError is to the heap.
Unbounded recursive calls result in stack space being used up.
The following example produces StackOverflowError:
class StackOverflowDemo
{
public static void unboundedRecursiveCall() {
unboundedRecursiveCall();
}
public static void main(String[] args)
{
unboundedRecursiveCall();
}
}
StackOverflowError is avoidable if recursive calls are bounded to prevent the aggregate total of incomplete in-memory calls (in bytes) from exceeding the stack size (in bytes).
The most common cause of stack overflows is excessively deep or infinite recursion. If this is your problem, this tutorial about Java Recursion could help understand the problem.
Here is an example of a recursive algorithm for reversing a singly linked list. On a laptop (with the specifications 4 GB memory, Intel Core i5 2.3 GHz CPU 64 bit and Windows 7), this function will run into StackOverflow error for a linked list of size close to 10,000.
My point is that we should use recursion judiciously, always taking into account of the scale of the system.
Often recursion can be converted to iterative program, which scales better. (One iterative version of the same algorithm is given at the bottom of the page. It reverses a singly linked list of size 1 million in 9 milliseconds.)
private static LinkedListNode doReverseRecursively(LinkedListNode x, LinkedListNode first){
LinkedListNode second = first.next;
first.next = x;
if(second != null){
return doReverseRecursively(first, second);
}else{
return first;
}
}
public static LinkedListNode reverseRecursively(LinkedListNode head){
return doReverseRecursively(null, head);
}
Iterative Version of the Same Algorithm:
public static LinkedListNode reverseIteratively(LinkedListNode head){
return doReverseIteratively(null, head);
}
private static LinkedListNode doReverseIteratively(LinkedListNode x, LinkedListNode first) {
while (first != null) {
LinkedListNode second = first.next;
first.next = x;
x = first;
if (second == null) {
break;
} else {
first = second;
}
}
return first;
}
public static LinkedListNode reverseIteratively(LinkedListNode head){
return doReverseIteratively(null, head);
}
The stack has a space limit that depends on the operating system. The normal size is 8 MB (in Ubuntu (Linux), you can check that limit with $ ulimit -u and it can be checked in other OS similarly). Any program makes use of the stack at runtime, but to fully know when it is used you need to check the assembly language. In x86_64 for example, the stack is used to:
Save the return address when making a procedure call
Save local variables
Save special registers to restore them later
Pass arguments to a procedure call (more than 6)
Other: random unused stack base, canary values, padding, ... etc.
If you don't know x86_64 (normal case) you only need to know when the specific high-level programming language you are using compile to those actions. For example in C:
(1) → a function call
(2) → local variables in function calls (including main)
(3) → local variables in function calls (not main)
(4) → a function call
(5) → normally a function call, it is generally irrelevant for a stack overflow.
So, in C, only local variables and function calls make use of the stack. The two (unique?) ways of making a stack overflow are:
Declaring too large local variables in main or in any function that it's called in (int array[10000][10000];)
A very deep or infinite recursion (too many function calls at the same time).
To avoid a StackOverflowError you can:
check if local variables are too big (order of 1 MB) → use the heap (malloc/calloc calls) or global variables.
check for infinite recursion → you know what to do... correct it!
check for normal too deep recursion → the easiest approach is to just change the implementation to be iterative.
Notice also that global variables, include libraries, etc... don't make use of the stack.
Only if the above does not work, change the stack size to the maximum on the specific OS. With Ubuntu for example: ulimit -s 32768 (32 MB). (This has never been the solution for any of my stack overflow errors, but I also don't have much experience.)
I have omitted special and/or not standard cases in C (such as usage of alloc() and similar) because if you are using them you should already know exactly what you are doing.
In a crunch, the below situation will bring a stack overflow error.
public class Example3 {
public static void main(String[] args) {
main(new String[1]);
}
}
A simple Java example that causes java.lang.StackOverflowError because of a bad recursive call:
class Human {
Human(){
new Animal();
}
}
class Animal extends Human {
Animal(){
super();
}
}
public class Test01 {
public static void main(String[] args) {
new Animal();
}
}
Many answers to this question are good. However, I would like to take a slightly different approach and give some more insight into how memory works and also a (simplified) visualization to better understand StackOverflow errors. This understanding does not only apply to Java but all processes alike.
On modern systems all new processes get their own virtual address space (VAS). In essence VAS is an abstraction layer provided by the operating system on top of physical memory in order to ensure processes do not interfere with each others memory. It's the kernels job to then map the virtual addresses provided to to the actual physical addresses.
VAS can be divided into a couple of sections:
In order to let the CPU know what it is supposed to do machine instructions must be loaded into memory. This is usually referred to as the code or text segment and of static size.
On top of that one can find the data segment and heap. The data segment is of fixed size and contains global or static variables.
As a program runs into special conditions it may need to additionally allocate data, which is where the heap comes into play and is therefore able to dynamically grow in size.
The stack is located on the other side of the virtual address space and (among other things) keeps track of all function calls using a LIFO data structure. Similar to the heap a program may need additional space during runtime to keep track of new function calls being invoked. Since the stack is located on the other side of the VAS it is growing into the opposite direction i.e. towards the heap.
TL;DR
This is where the StackOverflow error comes into play.
Since the stack grows down (towards the heap) it may so happen that at some point in time it cannot grow further as it would overlap with the heap address space. Once that happens the StackOverflow error occurs.
The most common reason as to why this happens is due to a bug in the program making recursive calls that do not terminate properly.
Note that on some systems VAS may behave slightly different an can be divided into even more segments, however, this general understanding applies to all UNIX systems.
Here's an example
public static void main(String[] args) {
System.out.println(add5(1));
}
public static int add5(int a) {
return add5(a) + 5;
}
A StackOverflowError basically is when you try to do something, that most likely calls itself, and goes on for infinity (or until it gives a StackOverflowError).
add5(a) will call itself, and then call itself again, and so on.
This is a typical case of java.lang.StackOverflowError... The method is recursively calling itself with no exit in doubleValue(), floatValue(), etc.
File Rational.java
public class Rational extends Number implements Comparable<Rational> {
private int num;
private int denom;
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
public int compareTo(Rational r) {
if ((num / denom) - (r.num / r.denom) > 0) {
return +1;
} else if ((num / denom) - (r.num / r.denom) < 0) {
return -1;
}
return 0;
}
public Rational add(Rational r) {
return new Rational(num + r.num, denom + r.denom);
}
public Rational sub(Rational r) {
return new Rational(num - r.num, denom - r.denom);
}
public Rational mul(Rational r) {
return new Rational(num * r.num, denom * r.denom);
}
public Rational div(Rational r) {
return new Rational(num * r.denom, denom * r.num);
}
public int gcd(Rational r) {
int i = 1;
while (i != 0) {
i = denom % r.denom;
denom = r.denom;
r.denom = i;
}
return denom;
}
public String toString() {
String a = num + "/" + denom;
return a;
}
public double doubleValue() {
return (double) doubleValue();
}
public float floatValue() {
return (float) floatValue();
}
public int intValue() {
return (int) intValue();
}
public long longValue() {
return (long) longValue();
}
}
File Main.java
public class Main {
public static void main(String[] args) {
Rational a = new Rational(2, 4);
Rational b = new Rational(2, 6);
System.out.println(a + " + " + b + " = " + a.add(b));
System.out.println(a + " - " + b + " = " + a.sub(b));
System.out.println(a + " * " + b + " = " + a.mul(b));
System.out.println(a + " / " + b + " = " + a.div(b));
Rational[] arr = {new Rational(7, 1), new Rational(6, 1),
new Rational(5, 1), new Rational(4, 1),
new Rational(3, 1), new Rational(2, 1),
new Rational(1, 1), new Rational(1, 2),
new Rational(1, 3), new Rational(1, 4),
new Rational(1, 5), new Rational(1, 6),
new Rational(1, 7), new Rational(1, 8),
new Rational(1, 9), new Rational(0, 1)};
selectSort(arr);
for (int i = 0; i < arr.length - 1; ++i) {
if (arr[i].compareTo(arr[i + 1]) > 0) {
System.exit(1);
}
}
Number n = new Rational(3, 2);
System.out.println(n.doubleValue());
System.out.println(n.floatValue());
System.out.println(n.intValue());
System.out.println(n.longValue());
}
public static <T extends Comparable<? super T>> void selectSort(T[] array) {
T temp;
int mini;
for (int i = 0; i < array.length - 1; ++i) {
mini = i;
for (int j = i + 1; j < array.length; ++j) {
if (array[j].compareTo(array[mini]) < 0) {
mini = j;
}
}
if (i != mini) {
temp = array[i];
array[i] = array[mini];
array[mini] = temp;
}
}
}
}
Result
2/4 + 2/6 = 4/10
Exception in thread "main" java.lang.StackOverflowError
2/4 - 2/6 = 0/-2
at com.xetrasu.Rational.doubleValue(Rational.java:64)
2/4 * 2/6 = 4/24
at com.xetrasu.Rational.doubleValue(Rational.java:64)
2/4 / 2/6 = 12/8
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
Here is the source code of StackOverflowError in OpenJDK 7.

Java Recursion - Did I do this right? [closed]

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 8 years ago.
Improve this question
My job is to write a recursive version to this method. From what I understand Recursion is starting with a base call (if something then return) followed by an else which unwinds back to the original base. Like starting with a deck, adding on to the deck then removing cards from the deck until you are back to the original deck.
With that in mind here it is.
public static long fact(int n)
{
long result = 1;
while(n > 0)
{
result = result * n;
n = n - 1;
}
return result;
}
//my recursive version:
public static void recFact(int n)
{
if(n==0)
{
return n; // ir 0 it really doesn't matter right?
}
else
{
return recFact(n-1);
}
}
This is just an example test problem for an exam I have coming up, just want to make sure I have a handle on recursion. Did I do this right? If not what am I missing? please no answers in questions, just tell me what I did wrong and maybe some advice on better ways to understand it.
Thanks.
No, this recursive solution is not correct.
For every positive n, you're just return rectFact(n-1), which will recourse until you reach 0, at which point it will return. In other words, your function will always return 0. You're missing the part where you multiply the current n with rectFact(n-1). Additionally, note that 0! is 1, not 0:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
else
{
return n * recFact(n-1);
}
}
And finally, since the if clause returns, the else is somewhat redundant. This doesn't affect the method's correctness, of course, but IMHO the code looks cleaner without it:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
return n * recFact(n-1);
}
Your recursive version does no multiplication, and it will return zero for any input. So no, you didn't do it right.
But, the recursive version DOES recurse, so you have that going for you! To understand what's going wrong, walk through a very simple case.
Client calls recFact(3)
This will return to client recFact(2)
Which will return to above recFact(1)
Which will return to above recFact(0)
Which will return to above 0.
There are two major things going wrong:
Your base case is wrong (zero is too low)
You're not doing any multiplication
Good attitude about not wanting the solution handed to you! Hopefully these pointers wil help you figure it out.
EDIT: Apparently I misunderstood your grammar and you did want the solution.
Any recursive function needs three things:
The terminating condition: This tells the function when to stop calling itself. This is very important to avoid infinite recursion and avoid stack overflow exceptions.
The actual processing: You need to run the actual processing within each function. In your non recursive case, this was result = result * n. This is missing from your recursive version!
A collector/agggregator variable: You need some way to store the partial result of the recursive calls below you. So you need some way to return the result of recFact so that you can include it in processing higher up in the call chain. Note that you say return recFact(n - 1) but in the definition recFact returns void. That should probably be an int.
Based from your example you are missing the return type of your recFact which is int
Also recFact will always return 0 because you are not multiplying n each time to the recursion call of the method.
There are two ways to write recursive routines. One is the "standard" way that we all are taught. This is one entry point that must first check to see if the recursive chain is at an end (the escape clause). If so, it returns the "end of chain" value and ends the recursion. If not at the end, it performs whatever calculation it needs to get a partial value according to the level and then calls itself passing a value the next increment closer to the end of the chain.
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int val ){
if( val < 2 ){
return 1;
}
else{
return recFact( val - 1 ) * val; // recursive call
}
}
//Output: "Fact(15) = 2004310016"
In regular recursion, a partial answer is maintained at each level which is used to supplement the answer from the next level. In the code above, the partial answer is val. When first called, this value is 15. It takes this value and multiplies it by the answer from Fact(14) to supply the complete answer to Fact(15). Fact(14) got its answer by multiplying 14 by the answer it got from Fact(13) and so on.
There is another type of recursion called tail recursion. This differs in that partial answers are passed to the next level instead of maintained at each level. This sounds complicated but in actuality, make the recursion process much simpler. Another difference is that there are two routines, one is non recursive and sets up the recursive routine. This is to maintain the standard API to users who only want to see (and should only have to see)
answer = routine( parameter );
The non-recursive routines provides this. It is also a convenient place to put one-time code such as error checking. Notice in the standard routine above, if the user passed in -15 instead of 15, the routine could bomb out. That means that in production code, such a test must be made. But this test will be performed every time the routine is entered which means the test will be made needlessly for all but the very first time. Also, as this must return an integer value, it cannot handle an initial value greater than 19 as that will result in a value that will overflow the 32-bit integer container.
public static final int MaxFactorialSeq = 20;
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int value ){
if( value < 0 || value > MaxFactorialSeq ){
throw new IllegalArgumentException(
"Factorial sequence value " + value + " is out of range." );
}
return recFact( value, 1 ); // initial invocation
}
private int recFact( int val, int acc ){
if( val < 2 ){
return acc;
}
else{
return recFact( val - 1, acc * val ); // recursive call
}
}
//Output: "Fact(15) = 2004310016"
Notice the public entry point contains range checking code. This is executed only once and the recursive routine does not have to make this check. It then calls the recursive version with an initial "seed" of 1.
The recursive routine, as before, checks to see if it is at the end of the chain. If so, it returns, not 1 as before, but the accumulator which at this point has the complete answer. The call chain then just rewinds back to the initial entry point in the non-recursive routine. There are no further calculations to be made as the answer is calculated on the way down rather than on the way up.
If you walk though it, the answer with standard recursion was reached by the sequence 15*14*13*...*2*1. With tail recursion, the answer was reached by the sequence 1*15*14*...*3*2. The final answer is, of course, the same. However, in my test with an initial value of 15, the standard recursion method took an average of 0.044 msecs and the tail recursion method took an average of 0.030 msecs. However, almost all that time difference is accounted for by the fact that I have the bounds checking in my standard recursion routine. Without it, the timing is much closer (0.036 to 0.030) but, of course, then you don't have error checking.
Not all recursive routines can use tail recursion. But then, not all recursive routines should be. It is a truism that any recursive function can be written using a loop. And generally should be. But a Factorial function like the ones above can never exceed 19 levels so they can be added to the lucky few.
The problem with recursion is that to understand recursion you must first understand recursion.
A recursive function is a function which calls itself, or calls a function which ultimately calls the first function again.
You have the recursion part right, since your function calls itself, and you have an "escape" clause so you don't get infinite recursion (a reason for the function not to call itself).
What you are lacking from your example though is the actual operation you are performing.
Also, instead of passing a counter, you need to pass your counter and the value you are multiplying, and then you need to return said multiplied value.
public static long recFact(int n, long val)
{
if(n==1)
{
return val;
}
else
{
return recFact(n-1, val) * n;
}
}

java.lang.StackOverflowError exception for large inputs

Basically, I'm writing a program to do a simple division manually where I want the decimal place upto 10^6 places. The program works for inputs <3000, but when I go higher, it shows:
Exception in thread "main" java.lang.StackOverflowError
Here's my code:
{
....
....
int N=100000;//nth place after decimal point
String res=obj.compute(N,103993.0,33102.0,ans); //division of 103993.0 by 33102.0
System.out.println(res);
}
public String compute (int n, double a, double b, String ans){
int x1=(int)a/(int)b;
double x2=a-x1*b;
double x3=x2*10;
int c=0;
if (n==0||n<0)
return ("3."+ans.substring(1));
else if (x3>b){
ans+=""+x1;
c=1;
}
else if(x3*10>b){
ans+=x1+"0";
c=10;
}
else if(x3*100>b){
ans+=x1+"00";
c=100;
}
else if(x3*1000>b){
ans+=x1+"000";
c=1000;
}
else if(x3*10000>b){
ans+=x1+"0000";
c=10000;
}
return compute(n-String.valueOf(c).length(),x3*c,b,ans);
}
I'm not any hard-core programmer of Java. I need help in tackling this situation. I read some SO posts about increasing the stack size, but I didn't understand the method.
Using recursivity for this kind of computation is a good idea, but every sub-call you make, stores pointers and other info in the stack, eventually filling it. I don't know the depths of the VM, but I think that JVM's max heap or stack size depends on how much contiguous free memory can be reserved, so your problem might be solved by using the -Xssparameter, that changes the size of the stack (e.g. java -Xss8M YourClass). If this still doesn't work or you cannot get enought memory, I would try with a 64-bit JVM.
If all that doesn't workk, contrary to the usual good practice I would try to do this program without recursivity.
I hope this helps!
The recursive call from compute() to compute is causing the stack to overflow. Alter your method to use a loop rather than recursion and it would scale much better. See the wikipedia page for different division algorithms you could use: https://en.wikipedia.org/wiki/Division_%28digital%29
Alternatively use BigDecimal like so:
public class Main {
public static void main(String... args) {
final int precision = 20;
MathContext mc = new MathContext(precision, RoundingMode.HALF_UP);
BigDecimal bd = new BigDecimal("103993.0");
BigDecimal d = new BigDecimal("33102.0");
BigDecimal r = bd.divide(d, mc);
System.out.println(r.toString());
}
}
Output:3.1415926530119026041
Set precision to get the number of decimal places you want.

Categories

Resources