Using a While loop to converge on a value

  • Thread starter Thread starter DaveC426913
  • Start date Start date
  • Tags Tags
    Loop Value
Click For Summary
The discussion revolves around a JavaScript coding issue related to iterating until a value converges. The original code attempts to compare a current value with a previous one to determine when to stop iterating. The problem arises when the last value is updated before the comparison, causing the loop to exit prematurely after only one iteration. Several solutions are proposed, including using a `do-while` loop to ensure at least one iteration occurs before checking for convergence. Participants suggest restructuring the code to avoid resetting the last value until after the new value is calculated. The conversation also touches on the importance of properly ordering operations within the loop to maintain clarity and functionality. Ultimately, a working solution is confirmed, demonstrating that the correct placement of variable assignments can resolve the issue of premature loop termination. The discussion highlights common programming pitfalls and effective debugging strategies.
DaveC426913
Gold Member
Messages
24,110
Reaction score
8,242
TL;DR
How preserve the last value to compare it to the new one without exiting the loop
My brain is misfiring.

I have a start value (integer) that I perform an operation on that will iteratively cause it to converge on some (unknown) integer value.
I stop the iteration when the new value is the same as the old one (i.e. it has stopped changing).
Until that happens, I keep iterating.
To know that it's converged, I set the lastVal equal to thisVal before iterating.
But as soon as I do this, it meets the criteria for exiting the loop.
So I only get one iteration.

This is JavaScript, but it works fine as pseudo-code:

Code:
                lastVal=-1
                thisVal=i;         
                while (thisVal!=lastVal){
                    thisVal = doAThingTo(thisVal);
                    counter++;
                    lastVal = thisVal; // here's the problem
                }
                prt(counter);

I tried testing it without setting it, but of course that doesn't make the problem go away:
Code:
                lastVal=-1
                thisVal=i;         
                while (thisVal!=lastVal){
                    if (doAThingTo(thisVal)) != lastVal){
                        thisVal = doAThingTo(thisVal);
                        counter++;
                        lastVal = thisVal; // still a problem
                    }
                    else{
                        //break;
                        lastVal = thisVal;
                    }
                }
                prt(counter);

What am I missing?
Maybe a third temp variable?

I guess I could do an infinite loop that breaks manually when the criteria is met...
Code:
                lastVal=-1
                thisVal=i;         
                while (true){
                    thisVal = doAThingTo(thisVal);
                    if (thisVal == lastVal) {
                        break;
                    }
                    else {
                        counter++;
                        lastVal = thisVal;
                    }
                }
                prt(counter);
 
Technology news on Phys.org
DaveC426913 said:
Summary: How preserve the last value to compare it to the new one without exiting the loop

This is JavaScript, but it works fine as pseudo-code:
Code:
                lastVal=-1
                thisVal=i;        
                while (thisVal!=lastVal){
                    thisVal = doAThingTo(thisVal);
                    counter++;
                    lastVal = thisVal; // here's the problem
                }
                prt(counter);
This was your first code example, which seems to be nearly equivalent to your second example, with the difference being that you are moving the conditional expression out of while, and putting it into an if ... else structure.

The simple example to the question you're asking in the Summary is to not reset lastVal to thisVal as you're doing in the last line of your while loop in the first two examples. That is, if I understand what you're trying to do.

Can you provide a sequence of numbers that you're working with, and what the desired outcome of your program should be?
 
I took my own advice, and took the conditional out of the while.

Code:
                thisVal=i;
                counter=0;
                while (true){
                    if (subtractHiLo(thisVal)==lastVal && counter!=0){
                        break;
                    }
                    else {
                        thisVal = subtractHiLo(thisVal);
                        counter++;
                        lastVal=thisVal;
                    }                
                }
Works great.

I am testing Kaprekar's constant.

For any integer from 0001 to 9999 (skipping homogenous numbers such as 2222 and 7777), the convergence will be on 6174, after a maximum of 7 iterations.

Attached is the text output of my JavaScript - all 9999 sequences. (I'd attach my HTML doc, but PF doesn't allow HTML or ZIP uploads.)

(Only took me about 2 hours, and most of that was unit testing my helper functions.)
 

Attachments

Tried and tested problem-solving technique:

1. Write a post asking for help to solve the problem. Anticipate any questions and nitpicks. Provide the source in a barebones, readable format.
2. Your attempt to write the problem clearly and concisely will reveal the flaw you did not see, and you will have the answer to your own question.
3. Delete the post without sending.

Works every time. (I missed step 3.)

:oldbiggrin:Thanks for your help.
 
  • Haha
Likes Klystron and anorlunda
DaveC426913 said:
Of course, that doesn't do anything to solve the problem, since the internal "lastVal=thisVal" will still trigger the break in the loop immediately after the first iteration.

You must be doing something else then. If doAThingTo(thisValue) returns a value that is different from thisValue then clearly lastVal != thisVal.
 
Filip Larsen said:
You must be doing something else then. If doAThingTo(thisValue) returns a value that is different from thisValue then clearly lastVal != thisVal.
Ah I see. You also moved the lastVal=thisVal to immediately above the doAThingTo() line - i.e. at the beginning of the loop. In my example, I do that at the end of the loop. That's the diff.
 
hmmm27 said:
The problem is grammatical : you need an UNTIL construct, not a WHILE.
...
Javascript's version is DO WHILE :
Filip's example, post 4, shows the Do While construct.

hmmm27 said:
I'll refrain from commenting on the poor choice of nomenclature.
Whose poor choice? Yours? That's OK.
 
  • #10
Yeah, sorry ; got stuck in a time loop... didn't see his post... and then deleted my post when I noticed his, without seeing your reply.

Anyways, you might find this a bit smoother : it gets rid of the - to mine eyes - awkwardness of the "-1" assignments kludges and the recursive-looking thisval = doathingto(thisval).

Code:
ints
  counter = 0,
  old_value,
  new_value = function(i).

do
  old_value = new_value,
  counter++,
  new_value = function(old_value),
while
  new_value != old_value.

print
  counter.

It looks like a superfluous function call, but the algorithm has to be primed before the loop iteration. If it was a long program you'd want to call an inline procedure which contains the function call (and probably the counter increment).

Depending on your preference, you may want to initialize counter = 1.

And no, not my nomenclature : "this" and "prev(ious)" are not semantically proximate. Or, maybe my brain's "misfiring" : I found it confusing. YMMV
 
Last edited:
  • #11
hmmm27 said:
Anyways, you might find this a bit smoother : it gets rid of the - to mine eyes - awkwardness of the "-1" assignments kludges and the recursive-looking thisval = doathingto(thisval).
I went with my code that I put in post 3. It works just as hoped.

hmmm27 said:
And no, not my nomenclature : "this" and "prev(ious)" are not semantically proximate. Or, maybe my brain's "misfiring" : I found it confusing. YMMV
?
No one has used "prev" or previous. We used lastVal (which, granted, is synonymous with 'previous').
 
  • #12
It may be nicer to change the chosen construct to Do ... While, or something else, but what's wrong with just doing it in the right order for your chosen construct?

lastVal=-1
thisVal=i;
while (thisVal!=lastVal){ // check for difference
lastVal = thisVal; //preserve oldVal
thisVal = doAThingTo(thisVal); // or thisVal = doAThingTo(lastVal) sounds nicer to me
counter++;
}
prt(counter);
 

Similar threads

Replies
11
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 0 ·
Replies
0
Views
1K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 4 ·
Replies
4
Views
3K
Replies
7
Views
6K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 2 ·
Replies
2
Views
8K
  • · Replies 1 ·
Replies
1
Views
4K