I've try to use long and double with c, k, n variables but netbeans shows me a stack overflow error:
public class Main {
public static void main(String[] args) {
double c=0; //combinatorial
double n=5;
double k=15;
c= factorial(n)/(factorial(k)*factorial(n-k));
System.out.print(n+" combinatorial "+k+" between "+c+"\n");
}
static double factorial (double number) {
if (number == 0)
return 1;
else
return number * factorial(number-1);
}
}
Exception in thread "main" java.lang.StackOverflowError
at co.combinatorial.Main.factorial(Main.java:26)
at co.combinatorial.Main.factorial(Main.java:29)
at co.combinatorial.Main.factorial(Main.java:29)
at co.combinatorial.Main.factorial(Main.java:29)
......
Java Result: 1
Do I have to use integer literals or long.parselong
What I am doing wrong?
From the initial values, n-k = -10. Since this is less than 0, your factorial method will never return
(number == 0) may not happen due to binary representation of number. Even with some tolerance level added, it is still incomplete this way. You may need negative number conformance. (10-10 maybe not zero)
Each time it goes deeper in function stack because of recursivity, it consumes more memory for function variables and parameters until java cannot plea more from operating system.
c= factorial(n)/(factorial(k)*factorial(n-k));
For n=5 and k=15,
factorial(n-k) would become: factorial(-10)
and then..
number*factorial(number-1) would give us: -10*factorial(-11),
and like this it would
continue indefinitely never reaching 0.
hence the stack will overflow.
Related
I'm making a program to print nth Fibonacci Number.
Method FIBBO(int n) uses a combination of long and BigInteger types to store the result of Fibonacci operations. The method is suppose to switch over to using BigInteger when it is deemed that prev+next>Long.MAX_VALUE using big_flag. However this program only works if i use Integer.MAX_VALUE in the 2nd loop.
When i use Long.MAX_VALUE, the 2nd loop of big_flag is never triggered now matter how large the value of n and i only get garbage values. I can't understand why my overflow logic is never activated when i use Long.MAX_VALUE.
import java.util.*;
import java.math.*;
public class fibbo_iteration{
public static void main(String argss[])
{
BigInteger result;
Scanner input=new Scanner(System.in);
int n=0;
System.out.println("Enter number of terms for fibbonacci sequence");
n=input.nextInt();
if(n<0){
System.out.println("Fibbonaci sequence cannot be generated for the entered negative value");
System.exit(1);
}
result=fibbo_iteration.FIBBO(n); //call
System.out.println(result.toString());
}
static BigInteger FIBBO(int n)
{
// variables
long sum=0L,prev=0L,next=1L;
BigInteger big_prev=new BigInteger("0"),big_next=new BigInteger("0"),big_sum=new BigInteger("0");
boolean big_flag=false;
for(int i=0;i<n;i++){
if(big_flag){
// System.out.println(big_sum.toString()); to use when printing a series upto n
big_prev=big_next;
big_next=big_sum;
big_sum=big_prev.add(big_next);
}
else if(prev+next>Long.MAX_VALUE){ // ***The program works abolutely correct if i replace LONG.MAX_VALUE with Integer.MAX_Value***
big_prev=new BigInteger(String.valueOf(prev));
big_next=new BigInteger(String.valueOf(next));
big_sum=big_prev.add(big_next);
big_flag=true; // this is supposed to signal the switch to BigInteger
System.out.println("Value exceeds Long");
}
else{
if(i==1){ // this if block accomodates the eccentricity of starting the fibbonaci sequence
sum=1L;
continue;
}
sum=prev+next;
prev=next;
next=sum;
System.out.println(sum);
}
}
return big_flag==true?big_sum:new BigInteger(String.valueOf(sum));
}
}
The max value of Long is really the maximum of the type. Any calculation above this is giving you... well results you apparently do not expect. A check of the kind prev+next>Long.MAX_VALUE is a nonsense. It will never be truthy.
A bit of change that should make your program work is: prev > Long.MAX_VALUE - next
If you want to understand in greater detail, you can use the comparison as I wrote it and debug, placing a breakpoint inside the if block. Try to see the value of prev+next. See how it goes negative. This is because you have reached values outside what long can store.
Use Math.addExact(long,long). Surround using try-catch and switch to BigInteger when the Exception is thrown.
try
{
sum=Math.addExact(prev, next);
prev=next;
next=sum;
System.out.println(sum);
}
catch(ArithmeticException overflow)//Out of range
{
big_prev=new BigInteger(String.valueOf(prev));
big_next=new BigInteger(String.valueOf(next));
big_sum=big_prev.add(big_next);
big_flag=true; // this is supposed to signal the switch to BigInteger
System.out.println("Value exceeds Long");
}
This snippet should be placed in the else block corresponding to if(big_flag).
Also see Integer Overflow.
Thank you for your time!
for value upto 2147483641 code is working fine after that it is returning 0(why)..
as per my understanding program should return 0 only when overflow occurs.. (for -2147483648 and 2147483647 ) not for value falling in the range.
Also please share any link for leading zero number reversal.. I could not find any online.
public class ReverseDigit {
public int reverse(int integer) {
boolean negflag=false;
if(integer<0){
negflag=true;
integer=integer*-1;
}
int rev=0;
int rem=0;
while(integer!=0){
rem=integer%10;
int newrev= rev*10+rem;
if((newrev-rem)/10!=rev){
return 0;
}
else{
rev=newrev;
}
integer=integer/10;
}
return rev = negflag?rev*-1:rev;
}
public static void main(String[] args) {
ReverseDigit rd = new ReverseDigit();
System.out.println(rd.reverse(**2147483642**));
}
}
This is happens because the reversed number of 2147483642 is 2463847412, and this number is greater then Intrgre.MAX_VALUE which is 2147483647, so the number became less than 0.
This is happens to 2147483623 too, because his reversed number is 3263847412, and this number is greater then Intrgre.MAX_VALUE.
To fix that, I see two possible solutions:
Use long instead of int.
Rewrite the method to work with String, because you aren't really do any calculations (You can use string.charAt(int index) to get the digits one bt one).
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.
It started from I want to compute 1+2+3+...+n, and
It is easy for me to figure out an recursive method to deal with repeat-plus-operation, and the code as follow:
public long toAccumulate(long num)
{
return num == 1 ? 1 : num + toAccumulate(num-1);
}
This method works just fine when use in a range of small number like 1 to 100, however, it fails to work when the parameter up to a big number like 1000000.
I wonder why?
And one leads to another, I write a repeat-times-operation method as follow:
public long toTimes(long num)
{
return num == 1 ? 1 : num * toTimes(num-1);
}
And here comes some interesting result. If I pass 100 as parameter, I will get 0. So I decrease my parameter's value, and I finally got some number when the parameter passing 60, but the result was a very weird negative number -8718968878589280256.
This got me thinking, but it didn't too much time for me to rethink something I have learnt from C, which is long long big data value type. And I assumed that negative number showed off is because the result data too big to fit in the current data type. What amazed me was I realize that there's a BigInteger class in Java, and I remembered this class can operate the big value data, so I changed the first code as follow:
public BigInteger toAccumulate(BigInteger num)
{
return num.equals(1) ? BigInteger.valueOf(1) : (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
}
But it still didn't work... and this is driving me crazy...
A question I found in the stack overflow which similar to mine
According to the people who answered the question, I guess it may be the same reason that cause the bug in my code.
But since the BigInteger class didn't work, I think this must be the solution to this kind of accumulation problem.
What will you people do when you need to accumulate some number and prevent it go out of the maximum of data type? But is this really the data type problem?
return num.equals(1)
? BigInteger.valueOf(1)
: (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
should probably be
return num.equals(BigInteger.valueOf(1))
? BigInteger.valueOf(1)
: (num.add(toAccumulate(num.subtract(BigInteger.valueOf(1)))));
...though frankly I'd write it as a method accepting an int and returning a BigInteger.
What if you try this:
public static BigInteger toAccumulate (BigInteger num)
{
if (num.equals(BigInteger.valueOf(1)))
{
return BigInteger.valueOf(1) ;
}
else
{
// 1+2+...+(n-1)+n = (n)(n+1)/2
BigInteger addOne = num.add(BigInteger.valueOf(1));
return num.multiply(addOne).divide(BigInteger.valueOf(2));
}
}
Here's how you can do the 1*2*3*....*(n-1)*n
public static BigInteger toTimes (BigInteger num)
{
// Should check for negative input here
BigInteger product = num;
// while num is greater than 1
while (num.compareTo(BigInteger.valueOf(1)) == 1)
{
BigInteger minusOne = num.subtract(BigInteger.valueOf(1));
product = product.multiply(minusOne);
num = minusOne; // num--;
}
return product;
}
Note: This is essentially the Factorial Function
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.