Loop mystery

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Loop mystery

Mark Vande Kamp
I have a loop structure that provides much different results depending on something that shouldn't make any difference (according to my current knowledge). Note that in the following examples I've cut out a bunch of irrelevant commands.


The first loop looks like:


Compute #Pass = 0.

LOOP #pv = 1 to 40.

* Entry point.
DO IF(EntryPoint_(#pv) = 1).
    *Increment pass counter, and start counting this pass.
    compute #Pass = #Pass + 1.
    compute Pageviews(#Pass) = 1.
END IF.

* Any other page.
if(EntryPoint_(#pv) = 0) Pageviews(#Pass) = Pageviews(#Pass) + 1.

END LOOP IF (#Pass = 5).


The second loop looks like:

Compute #Pass = 1.

LOOP #pv = 1 to 40.

* Entry point.
DO IF(EntryPoint_(#pv) = 1).
    compute Pageviews(#Pass) = 1.
END IF.

* Any other page.
if(EntryPoint_(#pv) = 0) Pageviews(#Pass) = Pageviews(#Pass) + 1.

*Increment pass counter if this isn't first loop and current EntryPoint = 1.
if (#pv > 1 and EntryPoint_(#pv) = 1) #Pass = #Pass + 1.

END LOOP IF (#Pass > 5).


The second example is preferable because it's nicest to exit the loop as soon as #Pass turns to 6. The problem is that the IF command for incrementing #Pass in the second loop appears to be incrementing even on the first iteration of the loop when #pv is 1. When I do frequency counts of PageViews1, I get more than twice as many counts of "1" with the second loop than I get with the first loop. The results of the first loop are what I want to get, but I'd love to understand what is going on so I don't make the mistake(?) that I have made in the second loop.

Mark

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: Loop mystery

Richard Ristow
At 01:51 PM 12/7/2009, Mark Vande Kamp wrote:
I have a loop structure that provides much different results depending on something that shouldn't make any difference (according to my current knowledge). Note that in the following examples I've cut out a bunch of irrelevant commands.

The first loop looks like this (code rewritten, cutting number of PageViews from 40 to 12, and number of Passes from 5 to 4):

Vector Ept=Ept01 TO Ept14.
VECTOR PgV(5,F3).

Compute #Pass = 0.

LOOP #pv = 1 to 14.
.  * Entry point.
.  DO IF(Ept(#pv) = 1).
.     *Increment pass counter, and start counting this pass.
.     compute #Pass = #Pass + 1.
.     compute PgV(#Pass) = 1.
.  END IF.
.  * Any other page.
.  if(Ept(#pv) = 0) PgV(#Pass) = PgV(#Pass) + 1.
END LOOP IF (#Pass = 4).
LIST.


The second loop looks like:

Vector Ept=Ept01 TO Ept14.
VECTOR PgV(5,F3).

Compute #Pass = 1.

LOOP #pv = 1 to 14.
.  * Entry point.
.  DO IF(Ept(#pv) = 1).
.     compute PgV(#Pass) = 1.
.  END IF.
.  * Any other page.
.  if(Ept(#pv) = 0) PgV(#Pass) = PgV(#Pass) + 1.

.  *Increment pass counter if this isn't first loop and current EntryPoint = 1.
.  if (#pv > 1 and Ept(#pv) = 1) #Pass = #Pass + 1.

END LOOP IF (#Pass > 4).

Here's the logic bug, I think: When you start with #Pass=1 (and first EntryPoint=1), PageViews(1) becomes 1 as it should be; #Pass is not incremented; and so, properly, PageViews(1) is incremented until you hit a new EntryPoint=1.

When that happens, at the beginning of the loop, #Pass is not incremented, so the PageViews count for the old #Pass is reset to 1.

Then, #Pass is incremented, and counting proceeds incrementing PageViews(2). But then, when you hit another EntryPoint=1, it's PageViews(2) that's reset to 1, before proceeding incrementing PageViews(3). In the end, all PageViews values will be 1, or untouched.

The problem is that the IF command for incrementing #Pass in the second loop appears to be incrementing even on the first iteration of the loop when #pv is 1.

I think that's a misdiagnosis; see above.

[The second LOOP form] is preferable because it's nicest to exit the loop as soon as #Pass turns to 6.

If you want to do that, look at the BREAK command; but the gain in efficiency is invisible. In any case, make sure #Pass has its new value, before any calculations that require the new value.

-Best wishes,
 Richard


 When I do frequency counts of PageViews1, I get more than twice as many counts of "1" with the second loop than I get with the first loop. The results of the first loop are what I want to get, but I'd love to understand what is going on so I don't make the mistake(?) that I have made in the second loop.

=============================
APPENDIX: Test data, and code
(Not finished, not working)
=============================
DATA LIST FREE/
  EPt01 TO Ept14 (14F2).
BEGIN DATA
1 0 1 0 0 1 0 0 0 1 0 0 1 0
END DATA.
LIST.
DATASET NAME     TestData.
DATASET COPY     Loop1.
DATASET ACTIVATE Loop1 WINDOW=FRONT.

Vector Ept=Ept01 TO Ept14.
VECTOR PgV(5,F3).

Compute #Pass = 0.

LOOP #pv = 1 to 14.
.  * Entry point.
.  DO IF(Ept(#pv) = 1).
.     *Increment pass counter, and start counting this pass.
.     compute #Pass = #Pass + 1.
.     compute PgV(#Pass) = 1.
.  END IF.
.  * Any other page.
.  if(Ept(#pv) = 0) PgV(#Pass) = PgV(#Pass) + 1.
END LOOP IF (#Pass = 4).
LIST.


*... The second loop looks like: ... .
DATASET ACTIVATE TestData.
DATASET COPY     Loop2.
DATASET ACTIVATE Loop2 WINDOW=FRONT.


Vector Ept=Ept01 TO Ept14.
VECTOR PgV(5,F3).

Compute #Pass = 1.

LOOP #pv = 1 to 14.
.  * Entry point.
.  DO IF(Ept(#pv) = 1).
.     compute PgV(#Pass) = 1.
.  END IF.
.  * Any other page.
.  if(Ept(#pv) = 0) PgV(#Pass) = PgV(#Pass) + 1.

.  *Increment pass counter if this isn't first loop and current EntryPoint = 1.
.  if (#pv > 1 and Ept(#pv) = 1) #Pass = #Pass + 1.

.  /**/ COMPUTE #PrvPass = #Pass-1.
.  /**/ PRINT / 'Loop pass ' #pv ':'
   /**/       / '

END LOOP IF (#Pass > 4).

LIST.

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD