For Loop in Visual Basic results wrong number of loops - for-loop

I don't understand why I get x with a value of 6 while I think it should be 5.
Sub Main()
Dim x = 0
For x = 1 To 5
Next
Console.WriteLine(x)
Console.ReadLine()
End Sub
Result: 6

The reason that x equals 6 is because of the nature of a loop. You put no code inside the body of the loop. If you printed your code there you would see
1
2
3
4
5
Each time Next is reached, x is incremented. The fifth time you go through the loop, x is incremented to 6. In most cases it's best to not use loop variables outside of their loop. Using a C style loop what I mean is a bit more clear
for (int i=0; i<=5; i++){}
The loop runs until the condition i <= 5 is not true. Since each time through the loop i is increased by 1 this occurs first when i equals 6. I used the variable i here because i is a much more common loop variable name to see than x.

Related

Why is Lua loops slow?

Lua is said to be a fast scripting language. But when I tested looping e.g.:
a = 0
while a < 1000000000 do
a = a + 1
end
It takes a lot of time (over 1 minute). Is it because Lua needs to copy and paste loop's content, and then evaluate?
I know that when evaluating you need to pop() items away from stack.
I tested this "speed-test" on Ruby too and it did the loop in about 20s.
EDIT:
Why is this so much faster on local variables? (~16 seconds to do same iteration but on local variable inside function)
Try the code below. It compares while vs for loops and globals vs local variables.
I get these numbers (with Lua 5.1.4, but they are similar for 5.3.2), which tell you the cost of using global variables in a loop:
WG 9.16 100
WL 1.96 467
FG 4.93 186
FL 1.18 776
Of course, these costs get diluted if you do real work inside the loop.
Here is the code:
local N=1e8
t0=os.clock()
a = 0
while a < N do
a = a + 1
end
t1=os.clock()-t0
print("WG",t1,math.floor(t1/t1*100+0.5))
t0=os.clock()
local a = 0
while a < N do
a = a + 1
end
t2=os.clock()-t0
print("WL",t2,math.floor(t1/t2*100+0.5))
t0=os.clock()
b = 0
for i=1,N do
b = b + 1
end
t3=os.clock()-t0
print("FG",t3,math.floor(t1/t3*100+0.5))
t0=os.clock()
local b = 0
for i=1,N do
b = b + 1
end
t4=os.clock()-t0
print("FL",t4,math.floor(t1/t4*100+0.5))
Your loop is inefficient and unpractical.
You're doing one billion iterations. That's not exactly "light".
Not to mention you're using a while loop to substitute a numeric for loop.

For loop with flexible stop variable

I need to write a loop
for x in (1..y)
where the y variable can be changed somehow. How can I do that?
For example:
for x in (1..y/x)
But it does not work.
Normally we'd use a loop do with a guard clause:
x = 1
loop do
break if x >= y
x += 1
...
end
Make sure y is larger than x or it'll never do anything. y can change if necessary and as long as it's greater than x the loop will continue. As soon as y drops below x the loop will terminate on the next iteration.
Note: I use >= because testing for equality is a bug-in-waiting. Sometimes we try to compare where x starts out greater than y or we are incrementing a float and comparing it to an integer or another float and using == and never hit the magic "equal" causing the loop to run away. Instead always check for a greater-than-or-equal to end the loop.
I think you might be confused about return values. This actually works fine, it's just that the return value is equal to the original range.
y = 4
for x in (1..y)
puts x
end
# 1
# 2
# 3
# 4
#=> 1..4
Here's a code snippet to prove it.

Decrementing a loop counter as loop is executing

I'm trying to decrement the counter of a for loop as the loop is running. Unfortunately, Lua doesn't seem to allow that. This piece of code should run forever:
for i = 1, 100 do
print (i)
i = i - 1
end
but it does, in fact, simply print the series 1-100. Is that by design? If so, how do I decrement the counter of a running loop (for example because the current cycle was disqualified and should run again)?
It's by design. From Lua reference manual:
3.3.5 – For Statement
All three control expressions are evaluated only once, before the loop starts. They must all result in numbers.
So modifying the value of i inside the loop won't change how the loop runs.
for i = 10, 1, -1 do
print(i)
end
If you want to step backwards through a table then do:
for i = #SomeTable, 1, -1 do
print(SomeTable[i].someproperty)
end
Yu Hao above linked to the correct manual page, but quoted the wrong part of it.
Here is the correct quote
for v = e1, e2, e3 do block end
is equivalent to the code:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
[..]
var, limit, and step are invisible variables. The names shown here are for explanatory purposes only.
In other words, the variable that's being looped over (called "var" above) and the variable exposed to the developer (called "v" above) are different. There is no way to access the former.

Does VBScript have increment operator?

For y = 1 to 10
y = y+1
print(y)
Next
For the above code the output which I get is 2,4,6,8,10. Shouldn't the o/p be 2,3,4,5,6,7,8,9,10
Can I consider y = y+1 as y++
The default step increment for a vbscript for loop is 1. By adding in y=y+1, you are effectively increasing your increment by 2 each cycle:
For y = 2 to 10 step 2
Wscript.echo y
Next
There is no "increment operator" as such; However you could consider step an increment operator in this context (both positive and negative).
y = y + 1 is similar as the intended concept y++.
You would probably be best using that type of operation inside a do/while loop where there are no auto increments eg:
y = 0
do while y < 10
y = y + 1
wscript.echo y
Loop
See this previous post:
Does VBScript have Increment Operators
in a For...Next loop, you won'T need to increase the counter value manualy.
You are increasing the value that is increased by the For loop:
For y = 1 to 10 ' starts at 1, next is 3
y = y+1 ' but you increase it to 2, increased to 4
print(y) ' prints 2, 4
Next ' Increases to 3, 5, up to 11, then stops because it's greater than 10
No, VB Script doesn't have an increment operator. VB script is based on BASIC which is a language meant for learning and the increment operator is considered to be confusing by many so it was never added on purpose.
As for your second question, to get the output you want remove y = y+1 line and change loop to For y = 2 to 10. Also, yes, y=y+1 is the same as y++ in most languages.

For Loop: can the end value come from the value of a variable?

I have a forvalues loop:
forvalues x = 1(1)50 {
/* Code goes here */
}
Instead of 50, ideally, I would like that value to come as follows. I have a variable name. Let length = length(name). Whatever the largest value is for length, I would like that to be in place of the 50. I could not figure how to write a forvalues loop in which the end point was not directly stated numerically.
I am thinking that I could deduce the maximum length of the variable as follows:
gen id = 1
gen length = length(name)
by id, sort: egen maxlength = max(length)
From there though I do not know how to store this value into the for loop.
Alternatively, would this be better coded by a while loop?
Something like:
gen x = 1
while (x <= maxlength) {
/* Same Code Here */
replace x = x + 1
}
Based on the documentation I've read, it is possible to use macros but with the caveat that changing the end of the range within the forvalues loop has no effect on the number of times the loop will occur. For instance, if length(name) is 50 when the forvalues loop starts, and you change the length of name within the loop, it will still only loop 50 times.
Technically, you'd be better off using a while loop since forvalues was intended to be used when the end of the range is a literal value. You can use a forvalues loop, but you should use a while loop.
Here's my source to back this up:
http://www.stata.com/manuals13/pforvalues.pdf
Specifically:
Technical note
It is not legal syntax to type
. scalar x = 3
. forvalues i = 1(1)x' {
2. local x =x' + 1
3. display `i'
4. }
forvalues requires literal numbers. Using macros, as shown in the following technical note, is
allowed.
And:
Using macros, as shown in the following technical note, is
allowed.
Technical note
The values of the loop bounds are determined once and for all the first time the loop is executed.
Changing the loop bounds will have no effect. For instance,
will not create an infinite loop. With `n' originally equal to 3, the loop will be performed three
times.
local n 3
forvalues i = 1(1)`n' {
local n = `n' + 1
display `i'
}
Output:
1
2
3
Here is the trick with Stata which I think may work for you. I am using the data auto from Stata datasets.
sysuse auto
Suppose the variable name here be price. Now you want the length of variable price.
sum price
gen length=r(N)
To see what is r(N) type return list after running the sum price.
In your loop it goes like follows: (Updated as per #Nick)
forvalues x = 1/`r(N)'{
/* Code goes here */
}
OR:
local length=r(N)
forvalue i=1/`length'{
dis "`i'"
}
Note: It is not clear why you want for loop.So my answer is restricted to what you only asked for.
#Metrics' first code won't quite work. Here is a better way, cutting out what I call the middle macro.
Start with something more like
. su price, meanonly
. forval j = 1/`r(N)' {
An equivalent approach to the one proposed by #Nick and #Metrics is the following:
sysuse auto, clear
count if !missing(price)
forvalues x = 1 / `r(N)' {
/* Code goes here */
}

Resources