Member Avatar for sammoto

So it's my first time trying to do a loop and I've come across something that I'm not experienced enough to explain... My program compiles fine, but after I enter my third number (variable "a", see code below) it just skips a line and does nothing. It just lets me type whatever I want for as long as I want, like so:

Enter a value for x0:
3
Enter a value for x1:
98
Enter a value for a:
10.3
sj
jd
d

j
wiw
mv
hello
why isn't this working...

sdf
j

That was from my Terminal window after compiling this program:

public class RootFinder {
    public static final double EPSILON = 0.00001;
    public static double function(double x) {
        return (Math.log(x + 1) + x);
    }
    public static double searchValue(double x0, double x1, double a) {
        double x = 0;
        boolean valid = (function(x0)<a) && (a<function(x1));
        if (!valid) {
            x = -1;
        } 
        else if ( (x0 <= -1)||(x1 <= -1) ) {
            x = -1;
        } 
        else {
            x = (x0 + x1)/2;
        }
        while (!(function(x)==a)||(Math.abs(function(x) - a) <= EPSILON)) {
            if ( (function(x0)<function(x)) && (function(x)<a) ) {
                x0 = x;
            } else if ((a<function(x)) && (function(x)<function(x1))) {
                x1 = x;
            }
        }
        return x;           
    }
    public static void main(String[] args) {
        java.util.Scanner reader = new java.util.Scanner(System.in);
        System.out.println("Enter a value for x0:");
        double x0 = reader.nextDouble();
        System.out.println("Enter a value for x1:");
        double x1 = reader.nextDouble();
        System.out.println("Enter a value for a:");
        double a = reader.nextDouble();
        double x = searchValue(x0, x1, a);
        if (x == -1) {
            System.out.println("No such value exists, try again…");

        } else {
            System.out.println("The root of the equation is " + function(x));
        }
    }
}

Did I somehow manage to write an infinite loop? I thought I was being careful... Before I inserted the loop, the program compiled fine and the main method managed to print the appropriate message, so I'm pretty sure it's the loop that is the problem.

Thanks in advance!

This is because your x variable does not change and you are using variable x is your condition for your while loop.I think you want to update the x variable instead of the x0 or x1 variable or maybe do your condition base on the value of x0 and x1?

while (!(function(x)==a)||(Math.abs(function(x) - a) <= EPSILON))

To see if the code has a loop, add some printlns inside of the loop that print out the values of the variables that are begin used in the loop. Be sure to use an id string with the print outs so you know what is being printed: println("var=" + var);
replace var with the names of the variables in your code

Member Avatar for sammoto

NormR1: I tried what you said, and it's not an infinite loop because it only printed "x1 = ..." once. But then it still did that thing where I could type whatever I want endlessly...

wen_cai: I think you're right, but I don't know how I could make the 'while' conidition related to x0/x1, or the body of the loop related more to 'x'. I don't know if you're familiar with the bisection algorithm method of finding the root of an equation, but essentially what I'm trying to do is the following: The user selects two initial x-values (x0 and x1) and an initial y-value (a), then the program calculates the midpoint between x0 and x1 to give x. It then compares f(x) to 'a' (this is at line 18 where the loop begins). As long as f(x) is not equal to a, or not within the 'epsilon' error, then the program should reassign the value of x to the 'place-holder' value of either x0 or x1 (i.e. the lower or upper limit of the section that I'm trying to find the root of), in an attempt to minimize the difference between f(x) and 'a'... Sorry if I didn't explain that well. I understand the problem with my code, I just don't know how to fix it - it's soo frustrating!

it's not an infinite loop because it only printed "x1 = ..." once.

Post the code that shows where you have the printlns. When I execute the code I get print outs forever until I cancel the program.

Member Avatar for sammoto
while (!(function(x)==a)||(Math.abs(function(x) - a) <= EPSILON)) {
            if ( (function(x0)<function(x)) && (function(x)<a) ) {
                x0 = x;
                System.out.println("x0 = "+x0);
            } else if ((a<function(x)) && (function(x)<function(x1))) {
                x1 = x;
                System.out.println("x1 = "+x1);
            }
        }

I'm still getting something that looks like this:

Enter a value for x0:
23.4
Enter a value for x1:
56.3
Enter a value for a:
35
x1 = 39.849999999999994

s
s
d
fd

d
d

What about when neither the if nor the else if are true?
Add an ending else clause at line 8 and put a println in it.

And add a println between lines 1 & 2 that prints all the variables values

Member Avatar for sammoto

K, NOW it's an infinite loop. Or at least, if it ever was before, I can actually see it now...

while (!(function(x)==a)||(Math.abs(function(x) - a) <= EPSILON)) {
            System.out.println("a = "+a);
            System.out.println("x = "+x);
            System.out.println("x0 = "+x0);
            System.out.println("x1 = "+x1);
            if ( (function(x0)<function(x)) && (function(x)<a) ) {
                x0 = x;
                System.out.println("x0 = "+x0);
            } else if ((a<function(x)) && (function(x)<function(x1))) {
                x1 = x;
                System.out.println("x1 = "+x1);
            } else {
                System.out.println("You've reached the end of the loop..");
            }
        }

So how do I fix this? Based on my previous description, do you understand what I'm trying to do? Is there a way to make a temporary variable to act as a "place-holder" like I was saying before? I think the root of my problem is that I'm thinking of this like a human would; I'm doing some mental manipulations that the computer can't do. Haha I'm having a really hard time trying to think like a computer...

Member Avatar for sammoto

what if I made two additional variables: lowerLimit and upperLimit? They would act as placeholders. So initially lowerLimit would have the value of x0, and upperLimit = x1. Then after I check the condition of the loop, the value of either lower- or upperLimit would switch to the value of x, depending on the appropriate if-statement...?

do you understand what I'm trying to do?

i do not know what the algorithm is you are trying to code. You need to explain it in a list of simple steps that can be converted to code.

Can you write the algorithm you are trying to implement as a list of simple steps in pseudo code?

One possible problem I see is that the code does not save and use the values returned by the function() method?
Should the program use the value returned by the method?

I don't see anything wrong with updating x0 and x1 like you are doing - more variables won't help. But there are two logic problems as far as I can see:
1. Your loop condition will always be true, regardless of what's in the loop. So your loop will always be infinite.
If f(x)!=a the condition is true, but if f(x)==a then abs(f(x)) will be zero, which is <= epsilon for all non-negative epsilons, so the condition is also true.
2. Line 13 is untrue. If you get to that else block then x0 and x1 will not have been changed, so the loop condition (even it that was correctly coded) would still be true. Line 13 should print "the loop is infinite", or do something to fix the situation.

ps Have you confused the operator priority??

!A||B
is evaluated as
(!A) || B
it is not the same as
!(A || B),
which may be what you intended?

pps:
for the "line 13" problem, you need to make a list of all the possible combinations of x0, x, x1, f(x0), f(x1). f(x), and a that you could encounter, then make sure that your if tests will either change xo or change x1 or exit the loop with an error, for every possible combination.
Suppose, for example, that value a cannot be found between x0 and x1? Suppose f(x) has a negative slope between x0 and x1? (etc)

Member Avatar for sammoto

You're right, James. I meant to do !(A || B) (see step 3) of the outline below). Still, it didn't fix the loop...

NormR1: Find the root of the equation f(x) = ln(x+1)+x, given a constant value, 'a'.
1) The user states the initial limits (lower limit = x0, upper limit = x1) to the trial/error process of finding the root of the equation, as well as the 'a' value to compare the root to.
2) After passing some checks (x != -1, because that produces a math error), the program finds the middle point between the limits and compares the corresponding y-value (i.e. f(x)) to 'a'.
3) If f(x) = a, or if the difference is <= EPSILON, then the root has been found and the program is done
4) If the above is not true, then the following happens:
4a) If f(x0) < f(x) < a, then x becomes the new lower limit, while x1 remains the upper limit, and you continue in this loop until step 3) is satisfied.
4b) If a < f(x) < f(x1), then x becomes the new upper limit, while x0 remains the lower limit, and you continue in this loop until step 3) is satisfied.

Here's a youtube video that I checked out to get a more visual representation of the method: Click Here

Where are the values of lower limit and the upper limit changed? The code only changes them one time.
Here is the debug print outs I get:
O lwrLmt=3.0, uprLmt=98.0 a=10.3
1 lwrLmt=3.0, uprLmt=50.5 a=10.3
1 lwrLmt=3.0, uprLmt=50.5 a=10.3
1 lwrLmt=3.0, uprLmt=50.5 a=10.3
1 lwrLmt=3.0, uprLmt=50.5 a=10.3
... rest are the same

A comment on the coding: The variable names would make it easier to read if they were lwrLimit and uprLimit vs x0 and x1

Member Avatar for sammoto

The code only changes them one time.

Ok, so there's my first probelm. After the user initially states the limits in the main method, I want the limits to continue changing in the searchValue method until the while-statement is satisfied. This is how the root can be narrowed down to within 0.00001 (epsilon) of 'a'.
So why is there only one iteration of the loop, even though the while-statement isn't true?

And thanks for the tip, I'm now starting to realize that variable naming is crucial to smooth reading...

why is there only one iteration of the loop

Is there a new version of the loop code? My version loops forever.

Member Avatar for sammoto

No, sorry - maybe I used the wrong terminology: by "one iteration", I meant that it's only changed once. There are still infinite identical iterations like you found. Again, this is the first time I've ever tried using a loop, so I don't even know where to begin troubleshooting, as I'm not experienced enough to realize what the trouble is haha... In other words: Thank you for your time and patience.

Go back to the algorithm definition and make sure you have it correctly defined.
It does not make sense to me that the values of the upper and lower limits only change once to be the value of x that is set only one time.
Should the value of x be changed inside of the loop?

BTW What is the correct answer?

Member Avatar for sammoto

Haha I don't know what the correct answer is... I need the upper or lower limit to continue changing until f(x) is close enough to 'a'. I don't know why the loop isn't working... My prof really didn't do a great job explaining the assignment to us. If you want I can upload the assignment file that he gave us, but I feel like that's asking too much of you. I'm just going to talk to my prof tomorrow and hopefully he can help me out. Thanks for all the help! I'm gonna keep on working on it later tonight and I'll let you know if I make any more progress

I don't know what the correct answer is..

Then you will never know when the program is working.

Member Avatar for sammoto

but the answer changes with different values of x0, x1, and a

I was assuming that there are known answers for many sets of: x0, x1, and a

You need to know the correct answer to know if the code is working.

After watching the video, I think I see your problem. You are missing a step. You are suppose to use the average of the upper limit and the lower limit. You did that for the 1st run but fail to continue using the average of your upper limit and lower limit after the 1st run. So, replace or add the code to replace x value with the average of the limits. You can replace your code from line 19 to line 23 with the code below.

if ( (function(x0)<function(x)) && (function(x)<a) ) {
    x0 = x;
    x = (x0 + x1) / 2;
} else if ((a<function(x)) && (function(x)<function(x1))) {
    x1 = x;
    x = (x0 + x1) / 2;
}
Member Avatar for sammoto

wen_cai: Of course! Haha I'm kicking myself... Thank you so much. See, I knew it was a simple thing I was missing. It's like in model loops when you're simply counting the number of iterations and you do i++; which changes the variable that the while-statement is based on

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.