I am writing a very basic Fortran Code to create the Ising model. However, I am stuck at the very last step - repeat the calculation until the most stable condition is achieved.
do
!Calculation (omitted here)
!Making a decision
if (E1 /= -64) then !not yet stable
if(dE > 0.0) then
call seed
call random_number(prob) ! random generate a number which is 0 <= Prob <= 1
Print *, prob
if(Prob < exp(-dE/T)) then
!do nothing as the flip was made
else
mat(b,c) = -mat(b,c) !flip the sign back, i.e. reject the change; only accept with probability of exp(-dE/T)
end if
else
end if !Since the sign has changed already, if dE<0, the move must be accepted. Therefore no additional move should be taken
else
end do
end if
end do
Apparently, Fortran doesn't like the second last end do statement as I didn't defined do at that particularly. All I want is to exit the do loop once E1 == -64.
In Fortran you can exit a do loop at any time using the exit statement.
do
...
if (condition) exit
end do
If your do loop is labelled, use the label in the exit statement too
outer: do
inner: do
...
if (condition) exit outer
end do inner
end do outer
Fortran 2008 allows the exit statement for other constructs too.
You should be able to use a while loop.
while (E1 [.ne. OR /=] -64) do
[your code]
end do
This requires E1 be updated inside the loop. Without this update, E1 will always not equal -64 and cause an infinite loop. Your code doesn't explicitly show this happening. I assume it does, but it's something to keep in mind.
Related
A colleague and I were trying to figure out a way of doing the equivalent of a "continue" statement within a VBScript "For/Next" loop.
Everywhere we looked we found people had no way to do this in VBScript without having nasty nestings, which is not an option for us since it is a quite big loop.
We came out with this idea. Would it work just as a "continue(to next iteration)"? Does anyone have any better workaround or improvement suggestion?
For i=1 to N
For workaroundloop = 1 to 1
[Code]
If Condition1 Then
Exit For
End If
[MoreCode]
If Condition2 Then
Exit For
End If
[MoreCode]
If Condition2 Then
Exit For
End If
[...]
Next
Next
Thanks for your comments
Your suggestion would work, but using a Do loop might be a little more readable.
This is actually an idiom in C - instead of using a goto, you can have a do { } while (0) loop with a break statement if you want to bail out of the construct early.
Dim i
For i = 0 To 10
Do
If i = 4 Then Exit Do
WScript.Echo i
Loop While False
Next
As crush suggests, it looks a little better if you remove the extra indentation level.
Dim i
For i = 0 To 10: Do
If i = 4 Then Exit Do
WScript.Echo i
Loop While False: Next
A solution I decided on involved the use of a boolean variable to track if the for loop should process its instructions or skip to the next iteration:
Dim continue
For Each item In collection
continue = True
If condition1 Then continue = False End If
If continue Then
'Do work
End If
Next
I found the nested loop solutions to be somewhat confusing readability wise. This method also has its own pitfalls since the loop doesn't immediately skip to the next iteration after encountering continue. It would be possible for a later condition to reverse the state of continue. It also has a secondary construct within the initial loop, and requires the declaration of an extra var.
Oh, VBScript...sigh.
Also, if you want to use the accepted answer, which isn't too bad readability wise, you could couple that with the use of : to merge the two loops into what appears to be one:
Dim i
For i = 0 To 10 : Do
If i = 4 Then Exit Do
WScript.Echo i
Loop While False : Next
I found it useful to eliminate the extra level of indentation.
One option would be to put all the code in the loop inside a Sub and then just return from that Sub when you want to "continue".
Not perfect, but I think it would be less confusing that the extra loop.
I use to use the Do, Loop a lot but I have started using a Sub or a Function that I could exit out of instead. It just seemed cleaner to me. If any variables you need are not global you will need to pass them to the Sub also.
For i=1 to N
DoWork i
Next
Sub DoWork(i)
[Code]
If Condition1 Then
Exit Sub
End If
[MoreCode]
If Condition2 Then
Exit Sub
End If
[MoreCode]
If Condition2 Then
Exit Sub
End If
[...]
End Sub
We can use a separate function for performing a continue statement work. suppose you have following problem:
for i=1 to 10
if(condition) then 'for loop body'
contionue
End If
Next
Here we will use a function call for for loop body:
for i=1 to 10
Call loopbody()
next
function loopbody()
if(condition) then 'for loop body'
Exit Function
End If
End Function
loop will continue for function exit statement....
I've always used an Do While loop. This works with both For type loops.
For iIndex = 0 to 100
Do
If bCondition then Exit Do
...
Loop While False
Next
IMHO, this just looks clean.
I just saw Crush's answer, at the bottom. Sorry for the duplicate answer.
Implement the iteration as a recursive function.
Function Iterate( i , N )
If i == N Then
Exit Function
End If
[Code]
If Condition1 Then
Call Iterate( i+1, N );
Exit Function
End If
[Code]
If Condition2 Then
Call Iterate( i+1, N );
Exit Function
End If
Call Iterate( i+1, N );
End Function
Start with a call to Iterate( 1, N )
Try use While/Wend and Do While / Loop statements...
i = 1
While i < N + 1
Do While true
[Code]
If Condition1 Then
Exit Do
End If
[MoreCode]
If Condition2 Then
Exit Do
End If
[...]
Exit Do
Loop
Wend
I think you are intended to contain ALL YOUR LOGIC under your if statement. Basically:
' PRINTS EVERYTHING EXCEPT 4
For i = 0 To 10
' you want to say
' If i = 4 CONTINUE but VBScript has no continue
If i <> 4 Then ' just invert the logic
WSH.Echo( i )
End If
Next
This can make the code a bit longer, but some people don't like break or continue anyway.
I wrote a program to check if a number is prime or not.
Here is the code:
program prime
integer n,i
print *, 'enter a number'
read *,n
do 10,i=2,n-1
if(mod(n,i).eq.0.0) then
print*, 'it is not prime'
read*
stop
end if
continue
if(n.eq.i)print *, 'it is prime'
read *
stop
end do
end program
However, there was a problem. I got an error:
Error: Statement label in ENDDO doesn't match DO label
The error in itself was understandable, the end do was not connected with the do loop. However, I cannot connect it as the program will not let me do so. Why is this?
With the statement
do 10,i=2,n-1
you are introducing a labelled DO construct. A labelled DO construct needs an appropriate termination statement, with matching label. In current Fortran, a matching labelled DO construct is terminated with
10 end do
or
10 continue
Labelled DO constructs are obsolescent in current Fortran, so the entire DO construct of the question can instead be written as
do i=2,n-1
...
end do
In the question, there is horribly confusing indentation. The continue statement is perhaps intended as the termination of the loop, but it isn't because it isn't labelled 10. continue is just a normal, do nothing, statement which has significance as a loop termination only through its label. Instead, the compiler sees the loop terminated by the end do, regardless of indentation, and then complains because it's missing the appropriate label.
The logic of the loop agrees with the indentation: the continue statement should be the end of the loop. There are three options
add a label 10 to the statement
change the continue to 10 end do
remove the 10 from the DO statement and change continue to end do
For each option, also delete the second end do.
Finally, with
if(n.eq.i) ...
coming after the loop, that condition is redundant: i will always have value n if it's reached.
program prime
integer n,i
print*, 'enter a number'
read*,n
do i=2,n-1
if (mod(n,i)==0.0) then
print*, 'it is not prime'
read*
stop
end if
end do
if (n==i) then
print*, 'it is prime'
read*
endif
end program prime
S = 'MSH, mdmOBX, TXA'
for u in string.gmatch(S, "([^,%s]+)"),1 do
l[k] = u
for a in string.gmatch(u,'.-([A-Z].*)'),1 do
g[z] = a
print(g)
_G["Map"..l[k]](Msg[g[z]],R[1])
end
_G["Map"..l[k]](Msg[l[k]],R[1])
end
I have above code, I want statement outside of inner loop to be executed only if inner for loop is not executed, I tried using 'break' keyword but that did not work and control was passed to outerloop .how to fix this?
Since Lua 5.2, you can just
goto label -- This statement goes to the jump-label label
::label:: -- The jump-label label
Using a flag variable which is checked after each loop which could set it for early bailout using successive break-statements is a classic of those fearing goto, or being condemned by lack of it.
local earlyreturn
for u in ... do
for a in ... do
if ... then
earlyreturn = true
break
end
end
if earlyreturn then
break
end
end
Anyway, you could also wrap your loops in a function and use return.
function(...)
for u in ... do
for a in ... do
if ... then
return
end
end
end
end(...)
Technically, to answer the "how to break out multiple loops": you can use a goto statement with an appropriately placed label, although it may not be the best solution. How about wrapping the body of the inner loop in an if instead?
Is there any programming language that has a do-until loop?
Example:
do
{
<statements>
}
until (<condition>);
which is basically equivalent to:
do
{
<statements>
}
while (<negated condition>);
NOTE: I'm looking for post-test loops.
Ruby has until.
i=0
begin
puts i
i += 1
end until i==5
VBA!
Do-Until-Loop
Do-Loop-Until
Although I think quite a number of people here would doubt if it is a real language at all, but well, BASIC is how Microsoft started (quite weak argument for many, I know)...
It is possible in VB.Net
bExitFromLoop = False
Do
'Executes the following Statement
Loop Until bExitFromLoop
It is also possible in SDF-P on BS2000 (Fujitsu/Siemens Operating System)
/ DECLARE-VARIABLE A
/ DECLARE-VARIABLE SWITCH-1(TYPE=*BOOLEAN)
/ SET-VARIABLE A = 5
/ SET-VARIABLE SWITCH-1 = ON
/ REPEAT
/ A = A + 10
/ IF (A > 50)
/ SET-VARIABLE SWITCH-1 = OFF
/ END-IF
/ UNTIL (SWITCH-1 = OFF)
/ SHOW-VARIABLE A
A = 55
Is is also possible is C or C++ using a macro that define until
Example (definition):
#define until(cond) while(!(##cond))
Example (utilisation):
int i = 0;
do {
cout << i << "\n";
i++;
} until(i == 5);
In VB we can find something like:
Reponse = InputBox("Please Enter Pwd")
Do Until Reponse = "Bob-pwr148" ...
Eiffel offers you an until loop.
from
x := 1
until
x > 100
loop
...
end
There is also an "across" loop as well. Both are very powerful and expressive.
The design of this loop has more to offer. There are two more parts to its grammar that will help us resolve two important "correctness" problems.
Endless loop protection.
Iteration failure detection.
Endless Loop Protection
Let's modify our loop code a little by adding a loop variant.
from
x := 1
v := 1_000
until
x > 100
variant
v
loop
...
v := v - 1
end
The loop variant is (essentially) a count-down variable, but not just any old variable. By using the variant keyword, we are telling the compiler to pay attention to v. Specifically, the compiler is going to generate code that watchdogs the v variable for two conditions:
Does v decrease with each iteration of the loop (are we counting down). It does no good to try and use a count-down variable if it is (in fact) not counting down, right? If the loop variant is not counting down (decreasing by any amount), then we throw an exception.
Does v ever reach a condition of less than zero? If so, then we throw an exception.
Both of these work together through the compiler and variant variable to detect when and if our iterating loop fails to iterate or iterates too many times.
In the example above, our code is communicating to us a story that it expects to iterate zero to 1_000 times, but not more. If it is more, then we stop the loop, which leaves us to wonder: Do we really have cases were we iterate more than 1_000 times, or is there something wrong that our condition is failing to become True?
Loop Invariant
Now that we know what a loop variant is, we need to understand what a loop invariant is.
The invariant is a set of one or more Boolean conditions that must hold True after each iteration through the loop. Why do we want these?
Imagine you have 1_000_000 iterations and one of them fails. You don't have time to walk through each iteration, examining it to see it is okay or not. So, you create a set of one or more conditions that are tested upon completion of each iteration. If the one or all of the conditions fail, then you know precisely which iteration (and its deterministic state) is causing the problem!
The loop invariant might look something like:
from
x := 1
y := 0
v := 1_000
invariant
y = x - 1
until
x > 100
variant
v
loop
...
x := x + 1
y := y + 1
v := v - 1
end
In the example above, y is trailing x by 1. We expect that after each iteration, y will always be x - 1. So, we create a loop invariant using the invariant keyword that states our Boolean assertion. If y fails to be x - 1, the loop will immediately throw an exception and let us know precisely which iteration has failed to keep the assertion True.
CONCLUSION
Our loop is now quite tight and secure—well guarded against failure (bugs, errors).
Below is a piece of code shown and doubts are regarding the implementation of loops
C := character'last; --'// SO code colorizer hack
I := 1;
K : loop
Done := C = character'first; --'
Count2 := I;
Exit K when Done;
C := character'pred(c); --'
I := I + 1;
end loop K;
Can anyone please tell me what does 'K' stands for.I guess its not a variable.How does 'K' control the execution of the loop?
K is the name of the loop. The end loop and Exit statements refer to that name, to make it clear what loop is being exited.
The Ada Reference Manual calls it a "loop_statement_identifier".
As noted, K is the loop's label. It allows you to identify a particular loop to aid readability, and also to selectively exit a specific loop from a set of nested enclosing ones (i.e. being a "goto"...shhh! :-)
Here's a contrived example (not compiled checked):
S : Unbounded_String;
F : File_Type;
Done_With_Line : Boolean := False;
All_Done : Boolean := False;
begin
Open(F, In_File, "data_file.dat");
File_Processor:
while not End_Of_File(F) loop
S := Get_Line(F);
Data_Processor:
for I in 1 .. Length(S) loop
Process_A_Character
(Data_Char => Element(S, I), -- Mode in
Line_Done => Done_With_Line, -- Mode out
Finished => All_Done); -- Mode out
-- If completely done, leave the outermost (file processing) loop
exit File_Processor when All_Done;
-- If just done with this line of data, go on to the next one.
exit Data_Processor when Done_With_Line;
end loop;
end loop File_Processor;
Close(F);
end;
K is essentially the name of the loop. The exit k tells the code to stop looping and go to the next statement after loop k ends.
You usually don't need to name loops, as you can just say exit and it will exit the enclosing loop. However, if you have a loop nested inside another loop, and you'd like to exit not the one immediately around the exit statement, but the outermost one, then doing something like this may be required.
K is a label that names the loop. Wow, it has been a long time since I've seen any Ada...