Learning Recursion, error when calling class - java

public class recursion {
public static void main(String[] args)
{
thisclass(0);
}
public static void thisclass(int z)
{
int x = 1;
int y = 3;
if (z==10)
{
System.out.println("Done");
}
else
{
System.out.println(x/y);
x++;
y= y+2;
thisclass(z++);
}
}
}
I'm learning recursion right now and when I get to the else statement in the thisclass method, I get an error after it prints an abnormal amount of zeros.
What I want the program to do is run 10 times and do something along the lines of Print 1/3 2/5 3/7 etc.
Where do I go wrong?

This line:
thisclass(z++);
Doesn't do what you think it does. It increments 'z' and then calls thisclass on the original value of z. It's a lot like doing:
int temp = z;
z = z + 1;
thisclass(temp);
You want to use preincrement instead of postincrement here:
thisclass(++z);
The answers that drunkenRabbit and Serdalis have posted are also valid. It won't work correctly until you've made all of these changes.

There are as far as I can tell (other than naming conventions) three things that are causing your program to not run as intended.
(1) You are doing integer division in your print, so 1/3 will be 0 (no decimals in ints).
Solution: Change int x and int y to double x and double y.
(2) You are post incrementing z when you pass it into the recursive call, meaning the recursive call does not see the new value, but rather the old one.
Solution: Pre-increment z thisclass(++z).
(3) You also likely mean to have x and y declared outside of your method, so that their updated values persist. (Instead you would just be printing the same value 10 times).
Solution:
double x = 1.0;
double y = 3.0;
public static void thisclass(int z){ ...

You are getting all those 0's because you are doing integer division, which does not support 1/3 etc.
You should change your code to use float's which will get rid of the 0 problem.
E.g.
float x = 1.0;
float y = 3.0;
You are also resetting the value of y with each call, so y will always be 3 at the beginning of the call and 5 at the end. You should check the value of z to see what the value of y should be.
Same can be said about the value of x.
The z is being post-incremented at each call, which will cause the value of z to not increase with each call, you should change the call to:
thisclass(++z);
To make tha value pre-incremented. Otherwise this call will go on forever.
Also, please don't call your methods thisclass is it very confusing.

Incrementing x and y in the else condition does not affect the recursive call variable. Think of recursion as a new call to the same method.
So, when making the recursive call x and y are initialized back to 1 and 3. You can pass x and y as a parameter so the updated value can be passed to each recursive call. Is one way to go about this...
Hope this helps :)

Notes:
it's better to use an initial call function that calls the recursive function itself, for initialization
use static data, otherwise they won't be preserved through the recursive calls
recur(z++) will execute like recur(z) resulting in an infinite recurrence, use recur(z+1) instead
Code:
public class recursion
{
public static void main(String[] args)
{
startRecursive(0);
}
// using static data
private static int x = 1, y = 3;
// initial call
public static void startRecursive (int initZ)
{
x = 1;
y = 3;
// avoid infinite recurrence
if (initZ > 10) initZ = 0;
recur(initZ);
}
// recursive function
public static void recur(int z)
{
if (z == 10)
{
System.out.println("Done");
}
else
{
System.out.println(x/y);
x += 1;
y += 2;
recur(z+1); // z++ will return z
}
}
}

Related

Calling function inside another function [duplicate]

Consider the following method:
void a ()
{
int x;
boolean b = false;
if (Math.random() < 0.5)
{
x = 0;
b = true;
}
if (b)
x++;
}
On x++ I get the "Local variable may not have been initialized" error. Clearly x will never be used uninitialized. Is there any way to suppress the warning except by initializing x? Thanks.
No, there is no way Java can examine all possible code paths for a program to determine if a variable has been initialized or not, so it takes the safe route and warns you.
So no, you will have to initialize your variable to get rid of this.
There is one :
void a () {
if (Math.random() < 0.5) {
int x = 1;
}
}
The compiler isn't responsible for devising and testing the algorithm. You are.
But maybe you should propose a more practical use case. Your example doesn't really show what's your goal.
Why don't you simply use
void a ()
{
int x;
boolean b = false;
if (Math.random() < 0.5)
{
x = 0;
b = true;
x++;
}
if (b) {
//do something else which does not use x
}
}
In the code why do you want to use x outside the first if block, all the logic involving x can be implemented in the first if block only, i don't see a case where you would need to use the other if block to use x.
EDIT: or You can also use:
void a ()
{
int x;
boolean b = (Math.random() < 0.5);
if (b) {
x=1
//do something
}
}
You can and should be defining the value of x unconditionally if it will be used later in your code.
There are a few ways to do this:
On initialization
int x = 0;
Because this is outside the conditional (if), Java won't complain.
Add else clause to conditional
if (Math.random() < 0.5)
{
x = 0;
b = true;
} else
{
x = 1;
}
Because there is an else to this if, and both code paths initialize x, Java will also be happy with this.
Move your usage of the variable into the conditional block
Clearly the question has a minimally-reproducible example, not a full one, but if you only ever want to use the variable conditionally, then it belongs in the conditional block.
if (Math.random() < 0.5)
{
x = 0;
x++;
}
If you don't aren't conditionally using the variable, then you need to provide an integer value to use in case Math.random() >= 0.5, using one of the solutions above.

Java Char increment [duplicate]

This question already has answers here:
What is x after "x = x++"?
(18 answers)
Closed 8 years ago.
I was executing the following code
class First
{
public static void main(String arg[])
{
char x= 'A';
x = x++;
System.out.println(x);
}
}
Here the output is A.
My question is why didn't x get incremented before printing.
You're using the post-increment operator incorrectly - you don't need to use assignment as well. And in this case it undermines what you're trying to do.
For context, remember that the post-increment operator increases the value, and returns the old value. That is, x++ is roughly equivalent to:
int x_initial = x;
x = x + 1;
return x_initial;
Hopefully now you can see why your code is failing to change x. If you expand it, it looks like:
char x= 'A';
char y;
{
y = x;
x = x + 1;
}
x = y;
System.out.println(x);
and the net effect of the assignment, is to set x back to what it was originally.
To fix - you can simply call x++. Or, if you want to make it clear there's some sort of assignment happening, x += 1 or even just x = x + 1 would do the same thing.
class First
{
public static void main(String arg[])
{
char x= 'A';
x = x++; // it is post increment as ++ sign is after x
System.out.println(x);
}
}
Post Increment(x++) : First execute the statement then increase the value by one.
Pre Increment (++x) : First increase the value by one then execute the statement.

Pointers and if statement error, in C code while converting in Java

I am trying to convert a C code to java, it's the Newton Raphson algorithm implementation. All is going well but there is a problem of pointers which were used in C code and i have removed them in java. The C code part is:
x = newton(x_0, error, max_iters, &iters, &converged); //Call to a function (newton)
if (converged) {
printf("Newton algorithm converged after %d steps.\n", iters);
printf("The approximate solution is %19.16e\n", x);
printf("f(%19.16e) = %19.16e\n", x, f(x));
} else
{
printf("Newton algorithm didn't converge after %d steps.\n",
iters);
printf("The final estimate was %19.16e\n", x);
printf("f(%19.16e) = %19.16e\n", x, f(x));
}
and the function definition is something like this:
double newton(double x_0, double error, int max_iters,
int* iters_p, int* converged_p)
Now the problem is that, the values of two pointer variables are just zero every time. Also the if(converged) shows an error message of incomoatible types. required boolean, found int. Below is the java code so please help overcome this.
//Member Functions///////
public
double function( double x)
{
return x*x - 2;
}
double F_Deriv( double x )
{
return 2.0*x;
}
double newton(double x_0, double error, int max_iters,int iters, int converged)
{
double x = x_0;
double x_prev;
int iter = 0;
do {
iter++;
x_prev = x;
x = x_prev - function(x_prev)/F_Deriv(x_prev);
}
while (Math.abs(x - x_prev) > error && iter < max_iters);
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
iters = iter;
return x;
}
/////Main Function///////
public static void main(String[] args) {
Newton_Raphson obj=new Newton_Raphson();
Scanner input=new Scanner(System.in);
double x_0; /* Initial guess */
double x; /* Approximate solution */
double error; /* Maximum error */
int max_iters; /* Maximum number of iterations */
int iters; /* Actual number of iterations */
int converged; /* Whether iteration converged */
System.out.println( "Enter Initial Solution: " );
x_0=input.nextDouble();
System.out.println( "Enter Error: " );
error=input.nextDouble();
System.out.println( "Enter Maximum Iterations: " );
max_iters=input.nextInt();
x = obj.newton(x_0, error, max_iters, iters, converged);
if(converged)
{
System.out.println("Newton algorithm converged after "+ iters +" steps.");
System.out.println("The approximate solution is "+ x);
}
else
{
System.out.println("Newton algorithm didn't converge after " + iters + " steps.");
System.out.println("The final estimate was " + x);
}
}
Java passes arguments by value, so
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
iters = iter;
doesn't change the passed arguments for the caller. These changes never leave the called function.
The simplest way to mimick out-parameters, resp. passed pointers in C, is to pass a one-length array,
double newton(double x_0, double error, int[] max_iters,int iters, boolean[] converged)
and set (and query) iters[0] resp. converged[0].
One problem is that this statement:
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
is not doing anything because Java is pass by value. So it won't affect the value of converged outside the method. You could instead return an object from your method which would contain 2 members: x and converged:
return new NewtonResult (x, iters, converged);
with NewtonResult defined as:
public class NewtonResult {
int x;
int iters;
boolean converged;
NewtonResult (int x, int iters, boolean converged) {
this.x = x;
this.iters = iters;
this.converged = converged;
}
}
Another problem in your code is that Java if requires a boolean when you are passing an int, so you need to change your condition to:
if (converged != 0) {
//
}
or even better make converged be a boolean.
The problem is that converged and iters are returned from the original C code. The use of pointers for those parameters is so that the parameters can mimic out semantics. Since Java only supports pass by value, you cannot return that information in the same way using plain method parameters.
The other issue is that older versions of C do not have a boolean type and so int is used instead. The flag to indicate convergence should be a boolean in Java.
So your code needs to return three pieces of information: the result (a floating point value), converged (a boolean value) and iters (an integer). You should wrap these up into an object and return them that way.
The class you need would look like this:
public class NewtonResult {
public boolean converged;
public double value;
public int iters;
}
You should change your newton method signature to be like so:
NewtonResult newton(double x_0, double error, int max_iters)
Finally, I think that tolerance would be a much better name than error for that parameter.
The class declaration is missing (public class Newton_Raphson...).
As said above, Java does not support arguments passed by reference, only by value, so you will need to wrap all those in a "Result" class.
public class Result {
public int x;
public int iters;
public int converged; // better replace this with a boolean in Java
}
and change the return type of your method to that Result class.
You cannot test an int as a boolean. You should test that it is different from 0 (since in C everything different than 0 is considered as true). Or consider using a boolean directly, it's much easier.
When passing premitive types such as int, boolean- in java as method parameters and changing them, in reality they will not be changed.
The parmeters passed are the copy of the real ones (they are actually being passed by value).
Initialize objects out of the varaiables and then pass them to the methods as:
Integer[] a = new Integer[1]; // For int a
Boolean[] b = new Boolean[1]; // For boolean b
a[0] = 1;
b[0] = true;
This way the copy of the reference of the passed object will be passed, and when you change the value of one of its elements like [0] above, it will be also changed in the real variable.

Recursion in Java program repeating same answer and not changing the value of "k"

What I'm trying to do is run 60 trials of this program. Each time I want the value of K to go down 1, until K=0. Currently i have only been able to get the program to repeat the same answer 60 time.
package heatloss;
/**
*
* #author eric
*/
public class HeatLoss {
public static void heatloss(double x, double m, double a, double k) {
double heatloss = x - m * (x - a);
if (k == 0) {
System.out.println("Done With Trials");
}
else {
System.out.println(heatloss);
heatloss(x,m,a,k-1);
}
}
public static void main(String[] args) {
double k = 60;
double old = 60+k;
double m = 0.10;
double air = 40;
heatloss(old, m ,air, k-1 );
}
}
You probably found it yourself: double heatloss = x - m * (x - a); always is the same, independent of k.
The value of k is decreasing, because your function runs 60 times, as you said. However:
heatloss = x - m * (x - a);
is a constant value, because it does not relate tok in any way, and thus
System.out.println(heatloss);
prints the same value every time.
To compare a double with 0 with == is a bad idea. Take look at this page: http://firstclassthoughts.co.uk/java/traps/java_double_traps.html
Your variable heatloss is never changing, because x, m, and a are never changing. This is why the same answer is being repeated each time.
Your k does go down in value. That's why it terminates. You never change x, m, or a in the next recursive call so why would you expect the value of heatloss to change if it's only dependent on x, m, and, a to change?

Java: Confused about the variable initialization concept

I'm new to Java and I'm having a bit of trouble understanding the concept of the declaration and the initialization of variables.
For example, when I do:
public class Foo {
public static void main (String[] args) {
int x, y;
for (x = 0 ; x < 10 ; x++) {
y = x + 1;
}
System.out.println(x);
System.out.println(y);
}
}
It does not compile and says that "variable y might not have been initialized."
However, it does not have any trouble if I tell it to just print out the x value after the loop. Of course it would work if I simply declared it in the beginning (saying int y = 0; or something like that), but I wanted to know why x is printed but not y.
Thanks in advance!
Edit:
I understand that the compiler doesn't actually check inside the loop to see if the variable would be initialized or not so it just says it might not have been initialized, but then why does the following code work? Does the compiler check the if loop but not the for loop?
public class Foo {
public static void main (String[] args) {
int x = 0, y;
if (x == 0) {
y = 1;
}
else {
y = 2;
}
System.out.println(y);
}
}
Edit 2:
It looks like it gives me the same error if I actually give another condition for the else part so that it would be:
if (x == 0) {
y = 1;
}
else if (x == 1) {
y = 2;
}
So I guess the other example worked since y was initialized in both the if and the else part, which means the y would always be initialized no matter what the condition given is. Now I really get it. Thank you!!
local variables don't have a default value and you need to initialize them. You are certainly setting the value of x (x=0), but the compiler doesn't check if the loop body will be actually entered. So give y a value of 0.
This is wrong:
public class Foo {
public static void main (String[] args) {
int = x, y; // Wrong
for (x = 0 ; x < 10 ; x++) {
y = x + 1;
}
System.out.println(x);
System.out.println(y);
}
}
This is correct:
public class Foo {
public static void main (String[] args) {
int x, y; // Declaration only: x and y are uninitialized
This is also correct:
public class Foo {
public static void main (String[] args) {
int x = 1, y = 10; // Declaration + initialization
'Hope that helps...
If you look in your code; you have initialized x to 0 in for loop and then incrementing it with x++. But you are initializing Y inside loop which may or may not execute at runtime (nothing to do with compile time). In Java, you have to initialize local variable before using it and if you are not doing so compiler will prompt the error. And that is why x is printed and not Y
It cannot be determined until run-time whether the for loop will be run even once. Therefore that initialization doesn't count (i.e., the compiler cannot depend on it, so it errors).
It cannot be determined until run-time which of the two -- the if or the else clause -- will fire. However, at compile-time we know that one OR the other will fire, so if you initialize in both, the compilation error goes away.
x gets initialized in the for loop (first argument)
Consider what could happen if your loop was
for (x = 0 ; x < someOtherVariable ; x++) {
and the value of someOtherVariable happened to be zero. The loop wouldn't run at all, so y would never be initialized.
Of course, the loop you wrote will always run ten times since the lower and upper bound are both hard-coded, but the compiler (apparently) doesn't analyze the code enough to prove that. It sees a variable that's only initialized within a loop, and following the general rule that a loop might not run at all, it complains that the variable might not be initialized.
BTW, int = x, y; isn't valid Java syntax: the equals sign doesn't belong there.
It depends on two things:
executes no matter what (here "x")
executes based on some constraint (here "y")
The compiler repels ambiguity in any case so it throws error on witnessing a variable initialization in a block which is conditionally executed.

Categories

Resources