java.lang.StackOverflowError exception for large inputs - java

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.

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

Simple micro-benchmark with JMH

Inspired by another question on Stack Overflow, I have written a micro-benchmark to check, what is more efficient:
conditionally checking for zero divisor or
catching and handling an ArithmeticException
Below is my code:
#State(Scope.Thread)
#BenchmarkMode(Mode.AverageTime)
#OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {
private int a = 10;
// a little bit less obvious than int b = 0;
private int b = (int) Math.floor(Math.random());
#Benchmark
public float conditional() {
if (b == 0) {
return 0;
} else {
return a / b;
}
}
#Benchmark
public float exceptional() {
try {
return a / b;
} catch (ArithmeticException aex) {
return 0;
}
}
}
I am totally new to JMH and not sure if the code is allright.
Is my benchmark correct? Do you see any mistakes?
Side not: please don't suggest asking on https://codereview.stackexchange.com. For Codereview code must already work as intended. I am not sure this benchmark works as intended.
The big thing I see missing is any sort of randomness. That will make it easier for the branch prediction to do its work, which will make both methods faster than they probably would be in practice for division by 0.
I would do three variations of each method:
with a random array with zeros intermixed, and have the benchmark be parameterized with an index into that array.
with a random array of non-zero numbers
with all 0s
That should give you a good idea of the overall performance, including branch prediction. For point (1), it may also be interesting to play with the ratio of 0s to non-0s.
I forget if JMH lets you parameterize directly on individual values of an array. If it does, then I'd use that. Otherwise, you'll have to parameterize on the index to that array. In that case, I would also put the all-0s in an array so that the stay access is part of all tests. I would also probably create a "control" that just accesses the array and returns its value, so that you can find out that overhead more directly.
Also, a minor nit: I don't think you need to return floats, since they'll just be converted from the ints that the division actually produces.

Recursive function throws java.lang.StackOverflowError

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.

why this code send me Stackoverflow in java

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.

proper way to store large numbers in a variable

I would like to play around with numbers and however elementary, Ive been writing algorithms for the fibonacci sequence and a brute force path for finding prime numbers!
Im not a programmer, just a math guy.
However, a problem I run into quiet often is that a long long, double and floats often run out of room.
If I wanted to continue to work in JAVA, in what way can I create my own data type so that I dont run out of room.
Conceptually, I thought to put 3 doubles together like so,
public class run {
static double a = 0;
static double b = 0;
//static double c = 0;
static void bignumber(boolean x) {
if (x == true && a < 999999999) {
++a;
} else if (x == true && a == 999999999) {
++b;
a = 0;
}
System.out.print(b + "." + a + " \n");
}
public static void main(String[] args) {
while(true) {
bignumber(true);
}
}
}
is there a better way to do this,
I would like to one day be able to say
mydataType X = 18476997032117414743068356202001644030185493386634
10171471785774910651696711161249859337684305435744
58561606154457179405222971773252466096064694607124
96237204420222697567566873784275623895087646784409
33285157496578843415088475528298186726451339863364
93190808467199043187438128336350279547028265329780
29349161558118810498449083195450098483937752272570
52578591944993870073695755688436933812779613089230
39256969525326162082367649031603655137144791393234
7169566988069
or any other number found on this site
I have also tried
package main;
import java.math.BigInteger;
public class run {
BigDecimal a = 184769970321174147430683562020019566988069;
public static void main(String[] args) {
}
}
But it still seems to be out of range
Use BigDecimal (instead of double), and BigInteger (instead of int, long) for that purpose, But you can only work with them by their methods. No operators, can be used.
Used like this:
BigInteger big = new BigInteger("4019832895734985478385764387592") // Strings...
big.add(new BigInteger("452872468924972568924762458767527");
Same with BigDecimal
BigDecimal is the class used in java where you need to represent very large or very small numbers, and maintain precision. The drawbacks are that it is not a primitive, so you can't use the normal math operators (+/-/*/etc), and that it can be a little processor/memory intensive.
You can store large numbers like this:
length
digits[]
and implement your math for them. This is not very complicated. As a hint, to make everything more simple you can store the digits in reverse order. This will make your math simpler to implement - you always add nr[k] with nr[k] and have room for transport for any length numbers, just remember to fill with 0 the shorter one.
In Knuth Seminumeric Algorithms book you can find a very nice implementation for all operations.

Categories

Resources